This is effective when a ref is updated from the super repository as well as all linked repositories because "repos" directory is shared between all repos. We could even forbid a ref update if it's some repo's HEAD. But I'd rather see a generic, permanent ref locking mechanism in place first and make use of it. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- refs.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/refs.c b/refs.c index 3691ef5..d856b1a 100644 --- a/refs.c +++ b/refs.c @@ -2462,6 +2462,41 @@ static int repack_without_ref(const char *refname) return repack_without_refs(&refname, 1); } +static void detach_repos_refs(const char *refname, const unsigned char *sha1) +{ + struct dirent *d; + DIR *dir; + + if (!strncmp(refname, "repos/", 6) || + !strchr(refname, '/') || + (dir = opendir(git_path("repos"))) == NULL) + return; + + while ((d = readdir(dir)) != NULL) { + struct strbuf sb_ref = STRBUF_INIT; + unsigned char ref_sha1[20]; + const char *ref; + int flags; + + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + strbuf_addf(&sb_ref, "repos/%s/HEAD", d->d_name); + ref = resolve_ref_unsafe(sb_ref.buf, ref_sha1, 1, &flags); + if (flags & REF_ISSYMREF && ref && !strcmp(ref, refname)) { + struct strbuf msg = STRBUF_INIT; + strbuf_addf(&msg, "repos: detach from %s by %s", + ref, real_path(get_git_dir())); + update_ref(msg.buf, sb_ref.buf, sha1, NULL, + REF_NODEREF, DIE_ON_ERR); + strbuf_release(&msg); + warning(_("detach HEAD of linked repository %s from %s"), + d->d_name, refname); + } + strbuf_release(&sb_ref); + } + closedir(dir); +} + static int delete_ref_loose(struct ref_lock *lock, int flag) { if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) { @@ -2485,6 +2520,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) lock = lock_ref_sha1_basic(refname, sha1, delopt, &flag); if (!lock) return 1; + detach_repos_refs(lock->ref_name, lock->old_sha1); ret |= delete_ref_loose(lock, flag); /* removing the loose one could have resurrected an earlier @@ -2790,6 +2826,7 @@ int write_ref_sha1(struct ref_lock *lock, unlock_ref(lock); return -1; } + detach_repos_refs(lock->ref_name, lock->old_sha1); if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 || write_in_full(lock->lock_fd, &term, 1) != 1 || close_ref(lock) < 0) { -- 1.8.5.1.77.g42c48fa -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html