Skip to content

Commit 0ce336f

Browse files
authored
Merge pull request #477 from thockin/v3-link-abspath
Allow --dest to be an absolute path (v3)
2 parents c0aa9f6 + ce8c4d3 commit 0ce336f

File tree

2 files changed

+62
-14
lines changed

2 files changed

+62
-14
lines changed

cmd/git-sync/main.go

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ var flSubmodules = flag.String("submodules", envString("GIT_SYNC_SUBMODULES", "r
6262
var flRoot = flag.String("root", envString("GIT_SYNC_ROOT", envString("HOME", "")+"/git"),
6363
"the root directory for git-sync operations, under which --dest will be created")
6464
var flDest = flag.String("dest", envString("GIT_SYNC_DEST", ""),
65-
"the name of (a symlink to) a directory in which to check-out files under --root (defaults to the leaf dir of --repo)")
65+
"the path (absolute or relative to --root) at which to create a symlink to the directory holding the checked-out files (defaults to the leaf dir of --repo)")
6666
var flErrorFile = flag.String("error-file", envString("GIT_SYNC_ERROR_FILE", ""),
6767
"the name of a file into which errors will be written under --root (defaults to \"\", disabling error reporting)")
6868
var flWait = flag.Float64("wait", envFloat("GIT_SYNC_WAIT", 1),
@@ -286,9 +286,8 @@ func main() {
286286
parts := strings.Split(strings.Trim(*flRepo, "/"), "/")
287287
*flDest = parts[len(parts)-1]
288288
}
289-
290-
if strings.Contains(*flDest, "/") {
291-
handleError(true, "ERROR: --dest must be a leaf name, not a path")
289+
if !filepath.IsAbs(*flDest) {
290+
*flDest = filepath.Join(*flRoot, *flDest)
292291
}
293292

294293
if *flWait < 0 {
@@ -646,28 +645,36 @@ func addUser() error {
646645
// directory and cleans up the previous worktree. If there was a previous
647646
// worktree, this returns the path to it.
648647
func updateSymlink(ctx context.Context, gitRoot, link, newDir string) (string, error) {
648+
linkDir, linkFile := filepath.Split(link)
649+
650+
// Make sure the link directory exists. We do this here, rather than at
651+
// startup because it might be under --root and that gets wiped in some
652+
// circumstances.
653+
if err := os.MkdirAll(filepath.Dir(linkDir), os.FileMode(int(0755))); err != nil {
654+
return "", fmt.Errorf("error making symlink dir: %v", err)
655+
}
656+
649657
// Get currently-linked repo directory (to be removed), unless it doesn't exist
650-
linkPath := filepath.Join(gitRoot, link)
651-
oldWorktreePath, err := filepath.EvalSymlinks(linkPath)
658+
oldWorktreePath, err := filepath.EvalSymlinks(link)
652659
if err != nil && !os.IsNotExist(err) {
653660
return "", fmt.Errorf("error accessing current worktree: %v", err)
654661
}
655662

656663
// newDir is absolute, so we need to change it to a relative path. This is
657664
// so it can be volume-mounted at another path and the symlink still works.
658-
newDirRelative, err := filepath.Rel(gitRoot, newDir)
665+
newDirRelative, err := filepath.Rel(linkDir, newDir)
659666
if err != nil {
660667
return "", fmt.Errorf("error converting to relative path: %v", err)
661668
}
662669

663670
const tmplink = "tmp-link"
664-
log.V(1).Info("creating tmp symlink", "root", gitRoot, "dst", newDirRelative, "src", tmplink)
665-
if _, err := cmdRunner.Run(ctx, gitRoot, "ln", "-snf", newDirRelative, tmplink); err != nil {
671+
log.V(1).Info("creating tmp symlink", "root", linkDir, "dst", newDirRelative, "src", tmplink)
672+
if _, err := cmdRunner.Run(ctx, linkDir, "ln", "-snf", newDirRelative, tmplink); err != nil {
666673
return "", fmt.Errorf("error creating symlink: %v", err)
667674
}
668675

669-
log.V(1).Info("renaming symlink", "root", gitRoot, "old_name", tmplink, "new_name", link)
670-
if _, err := cmdRunner.Run(ctx, gitRoot, "mv", "-T", tmplink, link); err != nil {
676+
log.V(1).Info("renaming symlink", "root", linkDir, "old_name", tmplink, "new_name", linkFile)
677+
if _, err := cmdRunner.Run(ctx, linkDir, "mv", "-T", tmplink, linkFile); err != nil {
671678
return "", fmt.Errorf("error replacing symlink: %v", err)
672679
}
673680

@@ -980,8 +987,7 @@ func syncRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot,
980987
askpassCount.WithLabelValues(metricKeySuccess).Inc()
981988
}
982989

983-
target := filepath.Join(gitRoot, dest)
984-
gitRepoPath := filepath.Join(target, ".git")
990+
gitRepoPath := filepath.Join(gitRoot, ".git")
985991
var hash string
986992
_, err := os.Stat(gitRepoPath)
987993
switch {
@@ -999,7 +1005,7 @@ func syncRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot,
9991005
return false, "", fmt.Errorf("error checking if repo exists %q: %v", gitRepoPath, err)
10001006
default:
10011007
// Not the first time. Figure out if the ref has changed.
1002-
local, remote, err := getRevs(ctx, target, branch, rev)
1008+
local, remote, err := getRevs(ctx, dest, branch, rev)
10031009
if err != nil {
10041010
return false, "", err
10051011
}

test_e2e.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,48 @@ function e2e::non_zero_exit() {
231231
)
232232
}
233233

234+
##############################################
235+
# Test HEAD one-time with an absolute-path link
236+
##############################################
237+
function e2e::absolute_dest() {
238+
echo "$FUNCNAME" > "$REPO"/file
239+
git -C "$REPO" commit -qam "$FUNCNAME"
240+
241+
GIT_SYNC \
242+
--one-time \
243+
--repo="file://$REPO" \
244+
--branch="$MAIN_BRANCH" \
245+
--rev=HEAD \
246+
--root="$ROOT/root" \
247+
--dest="$ROOT/other/dir/link" \
248+
>> "$1" 2>&1
249+
assert_file_absent "$ROOT"/root/link
250+
assert_link_exists "$ROOT"/other/dir/link
251+
assert_file_exists "$ROOT"/other/dir/link/file
252+
assert_file_eq "$ROOT"/other/dir/link/file "$FUNCNAME"
253+
}
254+
255+
##############################################
256+
# Test HEAD one-time with a subdir-path link
257+
##############################################
258+
function e2e::subdir_dest() {
259+
echo "$FUNCNAME" > "$REPO"/file
260+
git -C "$REPO" commit -qam "$FUNCNAME"
261+
262+
GIT_SYNC \
263+
--one-time \
264+
--repo="file://$REPO" \
265+
--branch="$MAIN_BRANCH" \
266+
--rev=HEAD \
267+
--root="$ROOT" \
268+
--dest="other/dir/link" \
269+
>> "$1" 2>&1
270+
assert_file_absent "$ROOT"/link
271+
assert_link_exists "$ROOT"/other/dir/link
272+
assert_file_exists "$ROOT"/other/dir/link/file
273+
assert_file_eq "$ROOT"/other/dir/link/file "$FUNCNAME"
274+
}
275+
234276
##############################################
235277
# Test default syncing (master)
236278
##############################################

0 commit comments

Comments
 (0)