Skip to content

Commit b9fac09

Browse files
calebdwttaylorr
authored andcommitted
worktree: add relativeWorktrees extension
A new extension, `relativeWorktrees`, is added to indicate that at least one worktree in the repository has been linked with relative paths. This extension is automatically set when a worktree is created or repaired using the `--relative-paths` option, or when the `worktree.useRelativePaths` config is set to `true`. The `relativeWorktrees` extension ensures older Git versions do not attempt to automatically prune worktrees with relative paths, as they would not not recognize the paths as being valid. Suggested-by: Junio C Hamano <[email protected]> Signed-off-by: Caleb White <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent 9bf2314 commit b9fac09

File tree

7 files changed

+37
-0
lines changed

7 files changed

+37
-0
lines changed

Documentation/config/extensions.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ Note that this setting should only be set by linkgit:git-init[1] or
6363
linkgit:git-clone[1]. Trying to change it after initialization will not
6464
work and will produce hard-to-diagnose issues.
6565

66+
relativeWorktrees::
67+
If enabled, indicates at least one worktree has been linked with
68+
relative paths. Automatically set if a worktree has been created or
69+
repaired with either the `--relative-paths` option or with the
70+
`worktree.useRelativePaths` config set to `true`.
71+
6672
worktreeConfig::
6773
If enabled, then worktrees will load config settings from the
6874
`$GIT_DIR/config.worktree` file in addition to the

repository.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ int repo_init(struct repository *repo,
283283
repo_set_compat_hash_algo(repo, format.compat_hash_algo);
284284
repo_set_ref_storage_format(repo, format.ref_storage_format);
285285
repo->repository_format_worktree_config = format.worktree_config;
286+
repo->repository_format_relative_worktrees = format.relative_worktrees;
286287

287288
/* take ownership of format.partial_clone */
288289
repo->repository_format_partial_clone = format.partial_clone;

repository.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ struct repository {
150150

151151
/* Configurations */
152152
int repository_format_worktree_config;
153+
int repository_format_relative_worktrees;
153154

154155
/* Indicate if a repository has a different 'commondir' from 'gitdir' */
155156
unsigned different_commondir:1;

setup.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,9 @@ static enum extension_result handle_extension(const char *var,
683683
"extensions.refstorage", value);
684684
data->ref_storage_format = format;
685685
return EXTENSION_OK;
686+
} else if (!strcmp(ext, "relativeworktrees")) {
687+
data->relative_worktrees = git_config_bool(var, value);
688+
return EXTENSION_OK;
686689
}
687690
return EXTENSION_UNKNOWN;
688691
}
@@ -1854,6 +1857,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
18541857
repo_fmt.ref_storage_format);
18551858
the_repository->repository_format_worktree_config =
18561859
repo_fmt.worktree_config;
1860+
the_repository->repository_format_relative_worktrees =
1861+
repo_fmt.relative_worktrees;
18571862
/* take ownership of repo_fmt.partial_clone */
18581863
the_repository->repository_format_partial_clone =
18591864
repo_fmt.partial_clone;
@@ -1950,6 +1955,8 @@ void check_repository_format(struct repository_format *fmt)
19501955
fmt->ref_storage_format);
19511956
the_repository->repository_format_worktree_config =
19521957
fmt->worktree_config;
1958+
the_repository->repository_format_relative_worktrees =
1959+
fmt->relative_worktrees;
19531960
the_repository->repository_format_partial_clone =
19541961
xstrdup_or_null(fmt->partial_clone);
19551962
clear_repository_format(&repo_fmt);

setup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct repository_format {
129129
int precious_objects;
130130
char *partial_clone; /* value of extensions.partialclone */
131131
int worktree_config;
132+
int relative_worktrees;
132133
int is_bare;
133134
int hash_algo;
134135
int compat_hash_algo;

t/t2400-worktree-add.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,4 +1248,17 @@ test_expect_success 'move repo without breaking relative internal links' '
12481248
)
12491249
'
12501250

1251+
test_expect_success 'relative worktree sets extension config' '
1252+
test_when_finished "rm -rf repo" &&
1253+
git init repo &&
1254+
git -C repo commit --allow-empty -m base &&
1255+
git -C repo worktree add --relative-paths ./foo &&
1256+
git -C repo config get core.repositoryformatversion >actual &&
1257+
echo 1 >expected &&
1258+
test_cmp expected actual &&
1259+
git -C repo config get extensions.relativeworktrees >actual &&
1260+
echo true >expected &&
1261+
test_cmp expected actual
1262+
'
1263+
12511264
test_done

worktree.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,14 @@ void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir)
10241024
strbuf_strip_suffix(&repo, "/gitdir");
10251025
strbuf_realpath(&repo, repo.buf, 1);
10261026

1027+
if (use_relative_paths && !the_repository->repository_format_relative_worktrees) {
1028+
if (upgrade_repository_format(1) < 0)
1029+
die(_("unable to upgrade repository format to support relative worktrees"));
1030+
if (git_config_set_gently("extensions.relativeWorktrees", "true"))
1031+
die(_("unable to set extensions.relativeWorktrees setting"));
1032+
the_repository->repository_format_relative_worktrees = 1;
1033+
}
1034+
10271035
if (use_relative_paths) {
10281036
write_file(gitdir.buf, "%s/.git", relative_path(path.buf, repo.buf, &tmp));
10291037
write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp));

0 commit comments

Comments
 (0)