Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

new methods Worktree.[AddGlob|RemoveBlob] and recursive Worktree.[Add|Remove] #739

Merged
merged 3 commits into from
Feb 28, 2018
Merged

Conversation

mcuadros
Copy link
Contributor

@mcuadros mcuadros commented Feb 1, 2018

Fixes: #456

@mcuadros mcuadros requested a review from ajnavarro February 1, 2018 18:18
// AddDirectory adds the files contents of a directory and all his
// sub-directories recursively in the worktree to the index. If any of the
// file is already staged in the index no error is returned.
func (w *Worktree) AddDirectory(path string) error {
Copy link
Contributor

@orirawlings orirawlings Feb 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API seems a little clumsy to me. Is there a reason we can't simply detect and support directory paths as part of the current Add function? A path string is already sufficient for a user to describe either directories or files.

Moreover, if we are going to provide separate functions for directories on Add we should also include separate functions MoveDirectory and RemoveDirectory for consistency.

In any case, I think we should simply extend the existing Add, Move, and Remove to support directory paths.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what should I return when I Add a repository? Because the signature returns a Hash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like Add returns the hash of the blob object that was added to the repository. If one is adding a directory, it might make sense to return the hash of the corresponding tree object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add doesn't create any tree object.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes. I see that. I guess this works then.

// AddGlob given a glob pattern adds all the matching files content and all his
// sub-directories recursively in the worktree to the index. If any of the
// file is already staged in the index no error is returned.
func (w *Worktree) AddGlob(pattern string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to support AddGlob we should also add a RemoveGlob for consistency in the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice point.

@mcuadros
Copy link
Contributor Author

@orirawlings PTAL

@mcuadros mcuadros changed the title new methods Worktree.[AddGlob|AddDirectory] new methods Worktree.[AddGlob|RemoveBlob] and recurive Add and Remove Feb 18, 2018
@mcuadros mcuadros changed the title new methods Worktree.[AddGlob|RemoveBlob] and recurive Add and Remove new methods Worktree.[AddGlob|RemoveBlob] and recursive Worktree.[Add|Remove] Feb 18, 2018
Copy link
Contributor

@orirawlings orirawlings left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really good. :)

I just had a few minor suggestions and questions.

@@ -51,8 +53,20 @@ type Index struct {
ResolveUndo *ResolveUndo
}

// Add creates a new Entry and returns it. The caller should check that not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caller should first check that another entry with the same path does not exist.

// the worktree.
ErrDestinationExists = errors.New("destination exists")
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
// file in the worktree.ErrNotDirectory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra ErrNotDirectory at end of this comment?

ErrDestinationExists = errors.New("destination exists")
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
// file in the worktree.ErrNotDirectory
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match any paths

?

And maybe change the comment to refer to path instead of file as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What match is files, so I thing is ok with files

return
}

// AddGlob given a glob pattern adds all the matching files content and all his
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to avoid the masculine pronoun, "his".

AddGlob adds all paths, matching pattern, to the index. If pattern matches a directory path, all directory contents are added to the index recursively. No error is returned if all matching paths are already staged in index.

}
return h, err

return
}

if s.File(path).Worktree == Unmodified {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be an optimization to move this check before the w.copyFileToStorage(path) call?

if err != nil {
return plumbing.ZeroHash, err
}

if err := w.deleteFromFilesystem(path); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just:

return hash, w.deleteFromFilesystem(path)

@@ -409,6 +585,43 @@ func (w *Worktree) deleteFromFilesystem(path string) error {
return err
}

// RemoveGlob given a glob pattern removes all the matching files content and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably avoid the masculine pronoun, "his", here too:

RemoveGlob removes all paths, matching pattern, from the index. If pattern matches a directory path, all directory contents are removed from the index recursively.

return err
}

if len(files) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious here how we might use this method for a paths that might still exist in the repository or index, but might have already been removed from the working directory. Will this check cause this method to return an error without attempting to remove them from the index?

Example:

$ git init
$ touch a; git add a; git commit -m first
[master (root-commit) 5d36496] first
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a
$ rm a; git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    a

no changes added to commit (use "git add" and/or "git commit -a")
$ git rm -- a*; git status
rm 'a'
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    a

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcuadros this seems like a bug to me. Can you confirm?

In git add, you can modify entries in the index even if the glob matches no paths in the current working directory. But this check looks like it would return an error before trying to update the index if the glob has no matches in the working directory.

$ git init
$ touch a; git add a
$ rm a; ls a*
$ git add -- a*; echo $?
0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a very complex behavior, the goal of this PR was speed up multiple Add calls.


return w.r.Storer.SetIndex(idx)
}

// Move moves or rename a file in the worktree and the index, directories are
// not supported.
func (w *Worktree) Move(from, to string) (plumbing.Hash, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we planning to wait for now on adding support for directories to this method?

Copy link
Contributor Author

@mcuadros mcuadros Feb 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added TODO

@mcuadros
Copy link
Contributor Author

@orirawlings PTAL

Copy link
Contributor

@orirawlings orirawlings left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I didn't have a look sooner.

Looks good. I just have one open question about using AddGlob to remove files from the index. It looks to me like the current code doesn't support that, but git add -- <glob> does.

return err
}

if len(files) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcuadros this seems like a bug to me. Can you confirm?

In git add, you can modify entries in the index even if the glob matches no paths in the current working directory. But this check looks like it would return an error before trying to update the index if the glob has no matches in the working directory.

$ git init
$ touch a; git add a
$ rm a; ls a*
$ git add -- a*; echo $?
0

}

var saveIndex bool
for _, file := range files {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also looks like we aren't trying to match patterns on things in the index, only paths that exist in the working directory. This is slightly different behavior than git add -- <glob> in cases where index entries should be removed (i.e. git add supports both adding AND removing entries from the index).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add, only adds files from the woktree to the index. The function Add should not do exactly the behavior of git add. This is a programmatically interface, so I rather keep it simple.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense. I'm just anticipating that this discrepancy will cause confusion for users and drive more issues being opened.

@mcuadros mcuadros merged commit 4397264 into src-d:master Feb 28, 2018
@inge4pres
Copy link

Hi 😄
can't understand if this is adding the support for recursive deletion of not empty folders, I am trying to do it with
worktree.Filesystem.Remove(path) where path is a folder containing some files and I'm getting error remove /tmp/path: directory not empty (using the clone with OS storage)

I looked a bit into billy's code and there is a RemoveAll function mimicking the standard lib's os.RemoveAll but it looks like in worktree.go it's only used in the rmFileAndDirIfEmpty function...

Any ideas?
Thanks

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants