From: Philip Oakley Date: Sun, 16 Jul 2017 13:04:13 GMT Subject: Re: [PATCH] RFC: A new type of symbolic refs Message-ID: In-Reply-To: <20170711010639.31398-1-sbeller@google.com> From: "Stefan Beller" Sent: Tuesday, July 11, 2017 2:06 AM >A symbolic ref can currently only point at (another symbolic) ref. > However are use cases for symbolic refs to point at other things > representing a commit-ish, such as gitlink entries in other > repositories. In this use case we can use such a symbolic link > to strengthen the relationship between a submodule and a superproject. > Examples: If I understand this correctly, the new type is the 'starts_with(buf, ))'. It just wasn't obvious from the text that the new type is "repo:" as you never spell it out in the commit message. Should it be included in the message? Have I understood correctly? -- Philip [I'll be off-line till Friday, so will pick up then] > > 1) It makes it easier to explain when we recurse into submodules and > to which sha1 the submodule is updated. > > Currently a submodule (or any repo) is either on a branch (i.e. > HEAD is a symbolic ref) or is in 'detached HEAD' state (HEAD is > a direct ref). > For submodules it is wrong to be on its own branch if it wants to be > controlled by the superproject as being on its own branch signals that > the submodule is independent and can move the HEAD freely. > Being in 'detached HEAD' state is the alternative to that and was > chosen when git-submodule was implemented, but it is equally wrong; > the lesser of two evils. > > Semantically the correct way to state a submodule is part of the > superproject is by pointing its HEAD to the superproject. > > We do have "reset/checkout --recurse-submodules" now, but it is > hard to explain what actually happens there (Which submodules are > updated? All of them! -- But I want a subset only!) > > With this new mode of symbolic refs, any submodule that tracks the > superproject, would 'automatically follow' the superproject as the > submodules HEAD moves when the superproject changes. > > 2) "git -C submodule commit" would behave the same as it would on branch > nowadays: It would make the commit in the submodule and then change > the target of the symbolic ref which would be the index of the > superproject! That implies that you do not need to 'git add' the > submodule to the superproject, but have it done automatically. > > Signed-off-by: Stefan Beller > --- > cache.h | 2 ++ > refs/files-backend.c | 10 ++++++++++ > submodule.c | 40 ++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 52 insertions(+) > > diff --git a/cache.h b/cache.h > index 71fe092644..4f79d23202 100644 > --- a/cache.h > +++ b/cache.h > @@ -2029,4 +2029,6 @@ void sleep_millisec(int millisec); > */ > void safe_create_dir(const char *dir, int share); > > +extern int read_external_symref(struct strbuf *from, struct strbuf *out); > + > #endif /* CACHE_H */ > diff --git a/refs/files-backend.c b/refs/files-backend.c > index 0404f2c233..f56f7b87ce 100644 > --- a/refs/files-backend.c > +++ b/refs/files-backend.c > @@ -713,6 +713,16 @@ static int files_read_raw_ref(struct ref_store > *ref_store, > goto out; > } > > + if (starts_with(buf, "repo:")) { > + if (read_external_symref(&sb_contents, referent)) { > + *type |= REF_ISBROKEN; > + ret = -1; > + goto out; > + } > + *type |= REF_ISSYMREF; > + ret = 0; > + } > + > /* > * Please note that FETCH_HEAD has additional > * data after the sha. > diff --git a/submodule.c b/submodule.c > index da2b484879..7297f90485 100644 > --- a/submodule.c > +++ b/submodule.c > @@ -2037,3 +2037,43 @@ int submodule_to_gitdir(struct strbuf *buf, const > char *submodule) > cleanup: > return ret; > } > + > +int read_external_symref(struct strbuf *from, struct strbuf *out) > +{ > + struct child_process cp = CHILD_PROCESS_INIT; > + const char *repo, *gitlink; > + int hint, code; > + struct strbuf **split = strbuf_split(from, 0); > + struct strbuf cmd_out = STRBUF_INIT; > + > + if (!split[0] || !split[1]) > + return -1; > + > + repo = split[0]->buf + 5; /* skip 'repo:' */ > + gitlink = split[1]->buf; > + > + argv_array_pushl(&cp.args, > + "ignored-first-arg", > + "-C", repo, > + "ls-tree", "-z", "HEAD", "--", gitlink, NULL); > + > + /* > + * 17 accounts for '160000 commit ', > + * the \t before path and trailing \0. > + */ > + hint = 17 + GIT_SHA1_HEXSZ + split[1]->len; > + code = capture_command(&cp, &cmd_out, hint); > + > + strbuf_release(split[0]); > + strbuf_release(split[1]); > + > + if (!code) { > + strbuf_reset(out); > + strbuf_add(out, cmd_out.buf + strlen("160000 commit "), > + GIT_SHA1_HEXSZ); > + } else > + return -1; > + > + return 0; > +} > + > -- > 2.13.2.695.g117ddefdb4 >