Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add support for reference clone#1007

Merged
technoweenie merged 6 commits into
git-lfs:masterfrom
jlehtnie:clone-reference
Apr 8, 2016
Merged

Add support for reference clone#1007
technoweenie merged 6 commits into
git-lfs:masterfrom
jlehtnie:clone-reference

Conversation

@jlehtnie

Copy link
Copy Markdown
Contributor

Fixes #459 and possibly helps for #515 and #766.

@jlehtnie jlehtnie force-pushed the clone-reference branch 2 times, most recently from 9fc129c to 2088b84 Compare February 15, 2016 21:49
@technoweenie technoweenie mentioned this pull request Feb 17, 2016
17 tasks
@technoweenie

Copy link
Copy Markdown
Contributor

Thanks for the PR. I'd love to get this into v1.2 (#844). I don't have a lot of experience with git references though, so it may take a little bit to review and test this properly though.

Comment thread lfs/pointer_smudge.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this should be wrapped in a utility function (same sequence used in fetch too, DRY)

@sinbad

sinbad commented Feb 23, 2016

Copy link
Copy Markdown
Contributor

This is looking good; I'd like to do a bit more testing with it too but I'd support this for 1.2. It's similar to the 'shared object store' idea I've tinkered with before, but I like that this uses an existing git principle. I'm also glad to see that hard links are now supported on Windows via os.Link in go 1.5; that wasn't the case in earlier Go versions and I've had write my own Windows implementation before. Benefitting from that does depend on NTFS partitions but your fallbacks cope with that. 👍

Comment thread lfs/util.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would make this safer by doing 2 things:

  1. Validate using os.SameFile to make sure src and dst are not the same
  2. Instead of calling CopyFileContents with dst as the direct output, instead copy to a temp file and then os.Rename on success. This will be more robust under unusual cases like forced termination.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@sinbad Thanks for your feedback. About the temporary file location: do you think it would be better to use os.TempDir() or store the tempfile in the destination directory? Latter is probably better from performance point of view because os.TempDir() might be in a different file system.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use lfs.TempDir, which is defined here, and set to .git/lfs/tmp here.

@sinbad

sinbad commented Apr 1, 2016

Copy link
Copy Markdown
Contributor

Other than the safety suggestions this works great for me. It actually behaves better than core git, which can potentially break if the referenced repo is garbage collected on shared objects (can't happen here because the local repo LFS object is either a hard link or a copy). Nice work!

Comment thread lfs/lfs.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I tend to prefer smaller guard clauses. What about:

func IfNoLocalObjExistsLinkOrCopyFromReferenceMedia(oid string, size int64) error {
    if ObjectExistsOfSize(oid, size) {
        return nil
    }

    // rest of the function
}

Also, I'm not thrilled with the name IfNoLocalObjExistsLinkOrCopyFromReferenceMedia. What about just LinkOrCopyFromReference ?

@technoweenie

Copy link
Copy Markdown
Contributor

First, thanks again for posting this, and for your patience while I take my sweet time reviewing it. I have two bigger pieces of feedback:

According to gitrepository-layout, objects/info/alternates can include multiple alternates. They can also come from $GIT_ALTERNATE_OBJECT_DIRECTORIES. Instead of setting LocalReferenceDir, I wonder if this could be added to lfs.Configuration instead. For example, the netrc support reads from the env and caches the parsed file. Then IfNoLocalObjExistsLinkOrCopyFromReferenceMedia() would loop through all the possible alternates, returning the first matching object.

The second, is that I'm not sure we need to link/copy those files from alternates to the current repository. It could result in a lot of duplicate files. It seems like git lfs smudge should just output the file from whatever path is necessary.

I'd say once the safety issue is resolved, and git lfs smudge supported, we could ship this as-is for v1.2, and improve/refactor things for v1.3.

@sinbad

sinbad commented Apr 5, 2016

Copy link
Copy Markdown
Contributor

The second, is that I'm not sure we need to link/copy those files from alternates to the current repository. It could result in a lot of duplicate files. It seems like git lfs smudge should just output the file from whatever path is necessary.

When it's a hardlink it won't actually be a duplicate, just a reference counted file object shared in both places. The only time this wouldn't work & fall back on a copy is if the reference is on a separate filesystem, or on Windows if you're using FAT instead of NTFS (should be pretty unlikely now).

I actually like the way it's done here better than the way git does it with .git/objects, which explicitly says that if you orphan objects in the reference repo they may disappear and therefore break referencing git repos. The link/copy stops this happening although in theory you would have pushed the lfs objects before orphaning them so it would just result in a repeat download in the referencing repo instead. Still, I quite like the inbuilt extra safety.

@technoweenie

Copy link
Copy Markdown
Contributor

I think the safety aspect is less important here than in Git. Git needs every object locally, otherwise basic operations don't work. The only thing Git LFS absolutely must have in the local .git/lfs/objects, are objects that are waiting to be pushed for the first time. Everything else can be read from the git reference/alternate, or downloaded from the server.

@jlehtnie

jlehtnie commented Apr 5, 2016

Copy link
Copy Markdown
Contributor Author

Personally I think that both of you have valid points here and maybe the behaviour should be configurable. E.g. one typical use case would be that the reference repository would be located on a network share. Now, if one is cloning a personal working repository to a laptop, copying the content to the local disk would be naturally preferable. On the other hand on a CI server it could safe lots of space if one could avoid the data duplication and simply refer to the network share.

@technoweenie

Copy link
Copy Markdown
Contributor

Now, if one is cloning a personal working repository to a laptop, copying the content to the local disk would be naturally preferable.

That's a great use case for the current behavior. I'm cool with shipping this now, and adding my suggestion later possibly 👍

Comment thread lfs/util.go Outdated
}
defer func() {
tmp.Close()
_ = os.Remove(tmp.Name())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not worth changing unless you have to make another change, but I tend to omit the _ = if I'm not going to do anything with it. Just some microfeedback :)

- Close instead of Sync since we are already done with the file
- Style: Omit return value for os.Remove()
@technoweenie

Copy link
Copy Markdown
Contributor

Thanks for all the tweaks! I still think there are more improvements that can be made, and will add them to the roadmap if you or someone else decides to take it on.

@technoweenie technoweenie merged commit 0ddb6f4 into git-lfs:master Apr 8, 2016
@jlehtnie

jlehtnie commented Apr 8, 2016

Copy link
Copy Markdown
Contributor Author

Thank you once more both of you for your valuable reviews! I'm happy to get it merged and I hope I will have the opportunity to work on the improvements later on too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants