Allow --dest to be an absolute path
This means it might live outside of --root.
This commit is contained in:
parent
d8bd262b87
commit
4fc67f5f5f
|
|
@ -67,7 +67,7 @@ var flSubmodules = pflag.String("submodules", envString("GIT_SYNC_SUBMODULES", "
|
|||
var flRoot = pflag.String("root", envString("GIT_SYNC_ROOT", ""),
|
||||
"the root directory for git-sync operations, under which --link will be created")
|
||||
var flLink = pflag.String("link", envString("GIT_SYNC_LINK", ""),
|
||||
"the name of a symlink, under --root, which points to a directory in which --repo is checked out (defaults to the leaf dir of --repo)")
|
||||
"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)")
|
||||
var flErrorFile = pflag.String("error-file", envString("GIT_SYNC_ERROR_FILE", ""),
|
||||
"the name of a file into which errors will be written under --root (defaults to \"\", disabling error reporting)")
|
||||
var flPeriod = pflag.Duration("period", envDuration("GIT_SYNC_PERIOD", 10*time.Second),
|
||||
|
|
@ -328,10 +328,10 @@ func main() {
|
|||
parts := strings.Split(strings.Trim(*flRepo, "/"), "/")
|
||||
*flLink = parts[len(parts)-1]
|
||||
}
|
||||
if strings.Contains(*flLink, "/") {
|
||||
handleError(log, true, "ERROR: --link must not contain '/'")
|
||||
if !filepath.IsAbs(*flLink) {
|
||||
*flLink = filepath.Join(*flRoot, *flLink)
|
||||
}
|
||||
if strings.HasPrefix(*flLink, ".") {
|
||||
if strings.HasPrefix(filepath.Base(*flLink), ".") {
|
||||
handleError(log, true, "ERROR: --link must not start with '.'")
|
||||
}
|
||||
|
||||
|
|
@ -829,28 +829,36 @@ func addUser() error {
|
|||
// directory and cleans up the previous worktree. If there was a previous
|
||||
// worktree, this returns the path to it.
|
||||
func (git *repoSync) UpdateSymlink(ctx context.Context, newDir string) (string, error) {
|
||||
linkDir, linkFile := filepath.Split(git.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
|
||||
linkPath := filepath.Join(git.root, git.link)
|
||||
oldWorktreePath, err := filepath.EvalSymlinks(linkPath)
|
||||
oldWorktreePath, err := filepath.EvalSymlinks(git.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(git.root, newDir)
|
||||
newDirRelative, err := filepath.Rel(linkDir, newDir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error converting to relative path: %v", err)
|
||||
}
|
||||
|
||||
const tmplink = "tmp-link"
|
||||
git.log.V(1).Info("creating tmp symlink", "root", git.root, "dst", newDirRelative, "src", tmplink)
|
||||
if _, err := git.run.Run(ctx, git.root, "ln", "-snf", newDirRelative, tmplink); err != nil {
|
||||
git.log.V(1).Info("creating tmp symlink", "root", linkDir, "dst", newDirRelative, "src", tmplink)
|
||||
if _, err := git.run.Run(ctx, linkDir, "ln", "-snf", newDirRelative, tmplink); err != nil {
|
||||
return "", fmt.Errorf("error creating symlink: %v", err)
|
||||
}
|
||||
|
||||
git.log.V(1).Info("renaming symlink", "root", git.root, "oldName", tmplink, "newName", git.link)
|
||||
if _, err := git.run.Run(ctx, git.root, "mv", "-T", tmplink, git.link); err != nil {
|
||||
git.log.V(1).Info("renaming symlink", "root", linkDir, "oldName", tmplink, "newName", linkFile)
|
||||
if _, err := git.run.Run(ctx, linkDir, "mv", "-T", tmplink, linkFile); err != nil {
|
||||
return "", fmt.Errorf("error replacing symlink: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -1188,8 +1196,7 @@ func (git *repoSync) SyncRepo(ctx context.Context) (bool, string, error) {
|
|||
askpassCount.WithLabelValues(metricKeySuccess).Inc()
|
||||
}
|
||||
|
||||
target := filepath.Join(git.root, git.link)
|
||||
gitRepoPath := filepath.Join(target, ".git")
|
||||
gitRepoPath := filepath.Join(git.root, ".git")
|
||||
var hash string
|
||||
_, err := os.Stat(gitRepoPath)
|
||||
switch {
|
||||
|
|
@ -1646,11 +1653,14 @@ OPTIONS
|
|||
--http-bind). (default: false)
|
||||
|
||||
--link <string>, $GIT_SYNC_LINK
|
||||
The name of the final symlink (under --root) which will point to the
|
||||
current git worktree. This must be a filename, not a path, and may
|
||||
not start with a period. The destination of this link (i.e.
|
||||
readlink()) is the currently checked out SHA. (default: the leaf
|
||||
dir of --repo)
|
||||
The path to at which to create a symlink which points to the
|
||||
current git directory, at the currently synced SHA. This may be an
|
||||
absolute path or a relative path, in which case it is relative to
|
||||
--root. The last path element is the name of the link and must not
|
||||
start with a period. Consumers of the synced files should always
|
||||
use this link. It is updated atomically and should always be
|
||||
valid. The basename of the target of the link is the current SHA).
|
||||
(default: the leaf dir of --repo)
|
||||
|
||||
--man
|
||||
Print this manual and exit.
|
||||
|
|
|
|||
42
test_e2e.sh
42
test_e2e.sh
|
|
@ -351,6 +351,48 @@ function e2e::head_once_root_exists_but_fails_sanity() {
|
|||
## FIXME: test when repo is valid git, but not ar ref we need
|
||||
## FIXME: test when repo is valid git, and is already correct
|
||||
|
||||
##############################################
|
||||
# Test HEAD one-time with an absolute-path link
|
||||
##############################################
|
||||
function e2e::absolute_link() {
|
||||
echo "$FUNCNAME" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME"
|
||||
|
||||
GIT_SYNC \
|
||||
--one-time \
|
||||
--repo="file://$REPO" \
|
||||
--branch="$MAIN_BRANCH" \
|
||||
--rev="HEAD" \
|
||||
--root="$ROOT/root" \
|
||||
--link="$ROOT/other/dir/link" \
|
||||
>> "$1" 2>&1
|
||||
assert_file_absent "$ROOT"/root/link
|
||||
assert_link_exists "$ROOT"/other/dir/link
|
||||
assert_file_exists "$ROOT"/other/dir/link/file
|
||||
assert_file_eq "$ROOT"/other/dir/link/file "$FUNCNAME"
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Test HEAD one-time with a subdir-path link
|
||||
##############################################
|
||||
function e2e::subdir_link() {
|
||||
echo "$FUNCNAME" > "$REPO"/file
|
||||
git -C "$REPO" commit -qam "$FUNCNAME"
|
||||
|
||||
GIT_SYNC \
|
||||
--one-time \
|
||||
--repo="file://$REPO" \
|
||||
--branch="$MAIN_BRANCH" \
|
||||
--rev="HEAD" \
|
||||
--root="$ROOT" \
|
||||
--link="other/dir/link" \
|
||||
>> "$1" 2>&1
|
||||
assert_file_absent "$ROOT"/link
|
||||
assert_link_exists "$ROOT"/other/dir/link
|
||||
assert_file_exists "$ROOT"/other/dir/link/file
|
||||
assert_file_eq "$ROOT"/other/dir/link/file "$FUNCNAME"
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Test default-branch syncing
|
||||
##############################################
|
||||
|
|
|
|||
Loading…
Reference in New Issue