Skip to content

Commit eb5e8d9

Browse files
druckdevJulian Prein
authored andcommitted
fix tag detection in linked worktrees
Previously, tags were not detected when they were checked out in a separate linked worktree. This occurred because gitstatus tried to read from `refs/tags` relative to the worktree-specific `.git` directory. However, since tags are shared refs, `refs/tags` will never exist there, but rather in the global git-dir (see the "REFS" section in git-worktree(1)). To fix this, remove the `worktrees/*` suffix from the repository path when needed.
1 parent 44504a2 commit eb5e8d9

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

src/tag_db.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,25 @@ git_refdb* RefDb(git_repository* repo) {
100100
return res;
101101
}
102102

103+
std::string GetGlobalRepoPath(git_repository* repo) {
104+
std::string dirname = git_repository_path(repo);
105+
if (git_repository_is_worktree(repo)) {
106+
// Unfortunately, to strip the worktrees/* suffix, we cannot
107+
// simply do:
108+
//
109+
// dirname.resize(dirname.rfind(".git/worktrees/") + ".git/"s.size());
110+
//
111+
// since the repository could be a submodule. In that case the
112+
// global git-dir path does not end in .git, but rather depends on
113+
// the path that the repo (i.e. submodule) has in the
114+
// superproject.
115+
auto pos = dirname.find_last_of('/', dirname.size() - 2);
116+
dirname.resize(pos - "worktrees"s.size());
117+
}
118+
119+
return dirname;
120+
}
121+
103122
} // namespace
104123

105124
TagDb::TagDb(git_repository* repo)
@@ -151,7 +170,7 @@ void TagDb::ReadLooseTags() {
151170
loose_tags_.clear();
152171
loose_arena_.Reuse();
153172

154-
std::string dirname = git_repository_path(repo_) + "refs/tags"s;
173+
std::string dirname = GetGlobalRepoPath(repo_) + "refs/tags"s;
155174
int dir_fd = open(dirname.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
156175
if (dir_fd < 0) return;
157176
ON_SCOPE_EXIT(&) { CHECK(!close(dir_fd)) << Errno(); };
@@ -175,7 +194,7 @@ void TagDb::UpdatePack() {
175194
std::memset(&pack_stat_, 0, sizeof(pack_stat_));
176195
};
177196

178-
std::string pack_path = git_repository_path(repo_) + "packed-refs"s;
197+
std::string pack_path = GetGlobalRepoPath(repo_) + "packed-refs"s;
179198
struct stat st;
180199
if (stat(pack_path.c_str(), &st)) {
181200
Reset();

0 commit comments

Comments
 (0)