in cmd/git-sync/main.go [647:682]
func updateSymlink(ctx context.Context, gitRoot, link, newDir string) (string, error) {
linkDir, linkFile := filepath.Split(link)
// Make sure the link directory exists. We do this here, rather than at
// startup because it might be under --root and that gets wiped in some
// circumstances.
if err := os.MkdirAll(filepath.Dir(linkDir), os.FileMode(int(0755))); err != nil {
return "", fmt.Errorf("error making symlink dir: %v", err)
}
// Get currently-linked repo directory (to be removed), unless it doesn't exist
oldWorktreePath, err := filepath.EvalSymlinks(link)
if err != nil && !os.IsNotExist(err) {
return "", fmt.Errorf("error accessing current worktree: %v", err)
}
// newDir is absolute, so we need to change it to a relative path. This is
// so it can be volume-mounted at another path and the symlink still works.
newDirRelative, err := filepath.Rel(linkDir, newDir)
if err != nil {
return "", fmt.Errorf("error converting to relative path: %v", err)
}
const tmplink = "tmp-link"
log.V(1).Info("creating tmp symlink", "root", linkDir, "dst", newDirRelative, "src", tmplink)
if _, err := cmdRunner.Run(ctx, linkDir, "ln", "-snf", newDirRelative, tmplink); err != nil {
return "", fmt.Errorf("error creating symlink: %v", err)
}
log.V(1).Info("renaming symlink", "root", linkDir, "old_name", tmplink, "new_name", linkFile)
if _, err := cmdRunner.Run(ctx, linkDir, "mv", "-T", tmplink, linkFile); err != nil {
return "", fmt.Errorf("error replacing symlink: %v", err)
}
return oldWorktreePath, nil
}