* Re: [PATCH v2] difftool: fix dir-diff index creation when in a subdirectory
From: Junio C Hamano @ 2016-12-12 21:35 UTC (permalink / raw)
To: David Aguilar; +Cc: Git ML, Frank Becker, Johannes Schindelin, John Keeping
In-Reply-To: <20161207101608.16058-1-davvid@gmail.com>
Thanks; queued and pushed out together with the follow-up series.
^ permalink raw reply
* Re: [PATCH v3 1/4] real_path: resolve symlinks by hand
From: Junio C Hamano @ 2016-12-12 22:19 UTC (permalink / raw)
To: Brandon Williams
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <1481566615-75299-2-git-send-email-bmwill@google.com>
Brandon Williams <bmwill@google.com> writes:
> +/* removes the last path component from 'path' except if 'path' is root */
> +static void strip_last_component(struct strbuf *path)
> +{
> + size_t offset = offset_1st_component(path->buf);
> + size_t len = path->len;
> +
> + /* Find start of the last component */
> + while (offset < len && !is_dir_sep(path->buf[len - 1]))
> + len--;
If somebody at a higher level in the callchain has already
normalized path, this is not a problem, but this will behave
"unexpectedly" when path ends with a dir_sep byte (or more).
E.g. for input path "foo/bar/", the above loop runs zero times and
then ...
> + /* Skip sequences of multiple path-separators */
> + while (offset < len && is_dir_sep(path->buf[len - 1]))
> + len--;
... the slash at the end is removed, leaving "foo/bar" in path.
> + strbuf_setlen(path, len);
> +}
> ...
> +/* get (and remove) the next component in 'remaining' and place it in 'next' */
> +static void get_next_component(struct strbuf *next, struct strbuf *remaining)
> +{
> + char *start = NULL;
> + char *end = NULL;
> +
> + strbuf_reset(next);
> +
> + /* look for the next component */
> + /* Skip sequences of multiple path-separators */
> + for (start = remaining->buf; is_dir_sep(*start); start++)
> + ; /* nothing */
> + /* Find end of the path component */
> + for (end = start; *end && !is_dir_sep(*end); end++)
> + ; /* nothing */
> +
> + strbuf_add(next, start, end - start);
> + /* remove the component from 'remaining' */
> + strbuf_remove(remaining, 0, end - remaining->buf);
> +}
Unlike the strip_last_component(), I think this one is more
carefully done and avoids getting fooled by //extra//slashes// at
the beginning or at the end, which does help in the correctness of
the loop we see below.
> @@ -58,74 +88,112 @@ static const char *real_path_internal(const char *path, int die_on_error)
> goto error_out;
> }
>
> + strbuf_reset(&resolved);
> +
> + if (is_absolute_path(path)) {
> + /* absolute path; start with only root as being resolved */
> + int offset = offset_1st_component(path);
> + strbuf_add(&resolved, path, offset);
> + strbuf_addstr(&remaining, path + offset);
> + } else {
> + /* relative path; can use CWD as the initial resolved path */
> + if (strbuf_getcwd(&resolved)) {
> + if (die_on_error)
> + die_errno("unable to get current working directory");
> + else
> + goto error_out;
> }
> + strbuf_addstr(&remaining, path);
> + }
>
> + /* Iterate over the remaining path components */
> + while (remaining.len > 0) {
> + get_next_component(&next, &remaining);
> +
> + if (next.len == 0) {
> + continue; /* empty component */
> + } else if (next.len == 1 && !strcmp(next.buf, ".")) {
> + continue; /* '.' component */
> + } else if (next.len == 2 && !strcmp(next.buf, "..")) {
> + /* '..' component; strip the last path component */
> + strip_last_component(&resolved);
Wouldn't this let "resolved" eventually run out of the path
components to strip for a malformed input e.g. "/a/../../b"?
> + ...
> + /*
> + * if there are still remaining components to resolve
> + * then append them to symlink
> + */
> + if (remaining.len) {
> + strbuf_addch(&symlink, '/');
This can add duplicate dir_sep if readlink(2)'ed contents of the
symbolic link already ends with a slash, but I think it (together
with the fact that the code does nothing to normalize what is read
from the symbolic link) probably does not matter, given the way how
get_next_component() is implemented.
> + strbuf_addbuf(&symlink, &remaining);
> + }
> +
> + /*
> + * use the symlink as the remaining components that
> + * need to be resloved
> + */
> + strbuf_swap(&symlink, &remaining);
> + }
> }
>
> + retval = resolved.buf;
> +
> error_out:
> + strbuf_release(&remaining);
> + strbuf_release(&next);
> + strbuf_release(&symlink);
>
> return retval;
> }
^ permalink raw reply
* Re: [PATCH v3 2/4] real_path: convert real_path_internal to strbuf_realpath
From: Junio C Hamano @ 2016-12-12 22:20 UTC (permalink / raw)
To: Brandon Williams
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <1481566615-75299-3-git-send-email-bmwill@google.com>
Brandon Williams <bmwill@google.com> writes:
> Change the name of real_path_internal to strbuf_realpath. In addition
> push the static strbuf up to its callers and instead take as a
> parameter a pointer to a strbuf to use for the final result.
>
> This change makes strbuf_realpath reentrant.
Yup, this step makes sense.
^ permalink raw reply
* Re: [PATCH v3 3/4] real_path: create real_pathdup
From: Junio C Hamano @ 2016-12-12 22:25 UTC (permalink / raw)
To: Brandon Williams
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <1481566615-75299-4-git-send-email-bmwill@google.com>
Brandon Williams <bmwill@google.com> writes:
> Create real_pathdup which returns a caller owned string of the resolved
> realpath based on the provide path.
>
> Signed-off-by: Brandon Williams <bmwill@google.com>
> ---
> abspath.c | 13 +++++++++++++
> cache.h | 1 +
> 2 files changed, 14 insertions(+)
>
> diff --git a/abspath.c b/abspath.c
> index 8c6c76b..79ee310 100644
> --- a/abspath.c
> +++ b/abspath.c
> @@ -205,6 +205,19 @@ const char *real_path_if_valid(const char *path)
> return strbuf_realpath(&realpath, path, 0);
> }
>
> +char *real_pathdup(const char *path)
> +{
> + struct strbuf realpath = STRBUF_INIT;
> + char *retval = NULL;
> +
> + if (strbuf_realpath(&realpath, path, 0))
> + retval = strbuf_detach(&realpath, NULL);
> +
> + strbuf_release(&realpath);
> +
> + return retval;
> +}
OK. Taken alone, the above makes a reader wonder if it still makes
sense for strbuf_realpath() to return realpath.buf (or NULL upon
error). An obvious alternative is to return 0 on success and -1 on
failure.
But other callers of strbuf_realpath() are mimicking the historical
"give a path in 'const char *', receive a path in 'const char *'
that you have to xstrdup() if you want to keep it" interface, and
this interface may be easier for them. I dunno.
> /*
> * Use this to get an absolute path from a relative one. If you want
> * to resolve links, you should use real_path.
> diff --git a/cache.h b/cache.h
> index 7a81294..e12a5d9 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -1068,6 +1068,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
> int die_on_error);
> const char *real_path(const char *path);
> const char *real_path_if_valid(const char *path);
> +char *real_pathdup(const char *path);
> const char *absolute_path(const char *path);
> const char *remove_leading_path(const char *in, const char *prefix);
> const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
^ permalink raw reply
* Re: [PATCH v3 4/4] real_path: have callers use real_pathdup and strbuf_realpath
From: Junio C Hamano @ 2016-12-12 22:26 UTC (permalink / raw)
To: Brandon Williams
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <1481566615-75299-5-git-send-email-bmwill@google.com>
Brandon Williams <bmwill@google.com> writes:
> Migrate callers of real_path() who duplicate the retern value to use
> real_pathdup or strbuf_realpath.
Looks good.
^ permalink raw reply
* Re: [PATCH 0/2] handling alternates paths with colons
From: Junio C Hamano @ 2016-12-12 22:37 UTC (permalink / raw)
To: Jeff King; +Cc: Johannes Sixt, Klaus Ethgen, git
In-Reply-To: <20161212194929.bdcihf7orjabzb2h@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> So here are patches that do that. It kicks in only when the first
> character of a path is a double-quote, and then expects the usual
> C-style quoting.
The quote being per delimited component is what makes this fifth
approach a huge win.
All sane components on a list-valued environment are still honored
and an insane component that has either a colon in the middle or
begins with a double-quote gets quoted. As long as nobody used a
path that begins with a double-quote as an element in such a
list-valued environment (and they cannot be, as using a non-absolute
path as an element does not make much sense), this will be safe, and
a path with a colon didn't work with Git unaware of the new quoting
rule anyway. Nice.
^ permalink raw reply
* Re: [RFC PATCH] send-email: allow a custom hook to prevent sending email
From: Junio C Hamano @ 2016-12-12 22:38 UTC (permalink / raw)
To: Stefan Beller; +Cc: Jeff King, Brandon Williams, git@vger.kernel.org
In-Reply-To: <CAGZ79kZVjsJjreKJgnOH1T-k-zfpfqivxw1gGm_dx4GU4tte2Q@mail.gmail.com>
Stefan Beller <sbeller@google.com> writes:
> $ git send-email 00* --cc=list --cc=bmwill --cc=duy --to=jch
> 0000-cover-letter.patch
> ...
> (mbox) Adding cc: Stefan Beller <sbeller@google.com> from line 'From:
> Stefan Beller <sbeller@google.com>'
>
> From: Stefan Beller <sbeller@google.com>
> To: gitster@pobox.com
> Cc: git@vger.kernel.org,
> bmwill@google.com,
> pclouds@gmail.com,
> Stefan Beller <sbeller@google.com>
> Subject: [PATCHv7 0/6] submodule absorbgitdirs
> Date: Mon, 12 Dec 2016 11:04:29 -0800
> Message-Id: <20161212190435.10358-1-sbeller@google.com>
> X-Mailer: git-send-email 2.11.0.rc2.49.ge1f3b0c.dirty
>
> Send this email? ([y]es|[n]o|[q]uit|[a]ll):
>
> ---
> This is usually where I just say "a" and carry on with life.
> The hook would ideally reformat the last lines to be
> ---
> X-Mailer: git-send-email 2.11.0.rc2.49.ge1f3b0c.dirty
> send-email hook thinks it is a bad idea to send out this series:
> <output of hook, e.g.
> referencing a typo in patch 5.
> or a mismatch of patch version numbers>
>
> Send this email? ([y]es|[n]o|[q]uit|[a]ll):
> ---
Yup, sounds sensible (the "... thinks it is a bad idea ..." line may
probably not be needed; the hook can say why it is unhappy itself).
Thanks.
^ permalink raw reply
* Re: [PATCH v3 1/4] real_path: resolve symlinks by hand
From: Brandon Williams @ 2016-12-12 22:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <xmqqd1gw94f1.fsf@gitster.mtv.corp.google.com>
On 12/12, Junio C Hamano wrote:
> Brandon Williams <bmwill@google.com> writes:
>
> > +/* removes the last path component from 'path' except if 'path' is root */
> > +static void strip_last_component(struct strbuf *path)
> > +{
> > + size_t offset = offset_1st_component(path->buf);
> > + size_t len = path->len;
> > +
> > + /* Find start of the last component */
> > + while (offset < len && !is_dir_sep(path->buf[len - 1]))
> > + len--;
>
> If somebody at a higher level in the callchain has already
> normalized path, this is not a problem, but this will behave
> "unexpectedly" when path ends with a dir_sep byte (or more).
>
> E.g. for input path "foo/bar/", the above loop runs zero times and
> then ...
>
> > + /* Skip sequences of multiple path-separators */
> > + while (offset < len && is_dir_sep(path->buf[len - 1]))
> > + len--;
>
> ... the slash at the end is removed, leaving "foo/bar" in path.
>
The way this is currently used I don't believe this scenario can happen
(since input to this shouldn't have trailing slashes), but if others
begin to use this function then yes, that is an implicit assumption. I
think it may be an ok assumption though since this is only called on
"resolved" which is the ouput and needs to be normalized to begin with. To
fix this we could simply add the while loop that strips dir_sep at the
beginning as well as at the end, like so:
/* Skip sequences of multiple path-separators */
while (offset < len && is_dir_sep(path->buf[len - 1]))
len--;
/* Skip sequences of multiple path-separators */
while (offset < len && !is_dir_sep(path->buf[len - 1]))
len--;
/* Skip sequences of multiple path-separators */
while (offset < len && is_dir_sep(path->buf[len - 1]))
len--;
> > + strbuf_setlen(path, len);
> > +}
> > ...
> > +/* get (and remove) the next component in 'remaining' and place it in 'next' */
> > +static void get_next_component(struct strbuf *next, struct strbuf *remaining)
> > +{
> > + char *start = NULL;
> > + char *end = NULL;
> > +
> > + strbuf_reset(next);
> > +
> > + /* look for the next component */
> > + /* Skip sequences of multiple path-separators */
> > + for (start = remaining->buf; is_dir_sep(*start); start++)
> > + ; /* nothing */
> > + /* Find end of the path component */
> > + for (end = start; *end && !is_dir_sep(*end); end++)
> > + ; /* nothing */
> > +
> > + strbuf_add(next, start, end - start);
> > + /* remove the component from 'remaining' */
> > + strbuf_remove(remaining, 0, end - remaining->buf);
> > +}
>
> Unlike the strip_last_component(), I think this one is more
> carefully done and avoids getting fooled by //extra//slashes// at
> the beginning or at the end, which does help in the correctness of
> the loop we see below.
>
> > @@ -58,74 +88,112 @@ static const char *real_path_internal(const char *path, int die_on_error)
> > goto error_out;
> > }
> >
> > + strbuf_reset(&resolved);
> > +
> > + if (is_absolute_path(path)) {
> > + /* absolute path; start with only root as being resolved */
> > + int offset = offset_1st_component(path);
> > + strbuf_add(&resolved, path, offset);
> > + strbuf_addstr(&remaining, path + offset);
> > + } else {
> > + /* relative path; can use CWD as the initial resolved path */
> > + if (strbuf_getcwd(&resolved)) {
> > + if (die_on_error)
> > + die_errno("unable to get current working directory");
> > + else
> > + goto error_out;
> > }
> > + strbuf_addstr(&remaining, path);
> > + }
> >
> > + /* Iterate over the remaining path components */
> > + while (remaining.len > 0) {
> > + get_next_component(&next, &remaining);
> > +
> > + if (next.len == 0) {
> > + continue; /* empty component */
> > + } else if (next.len == 1 && !strcmp(next.buf, ".")) {
> > + continue; /* '.' component */
> > + } else if (next.len == 2 && !strcmp(next.buf, "..")) {
> > + /* '..' component; strip the last path component */
> > + strip_last_component(&resolved);
>
> Wouldn't this let "resolved" eventually run out of the path
> components to strip for a malformed input e.g. "/a/../../b"?
>
As I understand it, that path is correct and would resolve to "/b". The
strip_last_component function doesn't allow striping the "1st" component
or the "root" component. So if resolved is "/" and we encounter a ".."
which requires striping of the last component, the result would be "/".
> > + ...
> > + /*
> > + * if there are still remaining components to resolve
> > + * then append them to symlink
> > + */
> > + if (remaining.len) {
> > + strbuf_addch(&symlink, '/');
>
> This can add duplicate dir_sep if readlink(2)'ed contents of the
> symbolic link already ends with a slash, but I think it (together
> with the fact that the code does nothing to normalize what is read
> from the symbolic link) probably does not matter, given the way how
> get_next_component() is implemented.
>
Yes, I think the way get_next_component() is written will account for
non-normalized symlink contents. This way we only have to worry about
normalizing input in one location (maybe two with
strip_last_component()).
> > + strbuf_addbuf(&symlink, &remaining);
> > + }
> > +
> > + /*
> > + * use the symlink as the remaining components that
> > + * need to be resloved
> > + */
> > + strbuf_swap(&symlink, &remaining);
> > + }
> > }
> >
> > + retval = resolved.buf;
> > +
> > error_out:
> > + strbuf_release(&remaining);
> > + strbuf_release(&next);
> > + strbuf_release(&symlink);
> >
> > return retval;
> > }
>
--
Brandon Williams
^ permalink raw reply
* Re: [PATCH v3 1/4] real_path: resolve symlinks by hand
From: Junio C Hamano @ 2016-12-12 23:32 UTC (permalink / raw)
To: Brandon Williams
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <20161212225006.GB193413@google.com>
Brandon Williams <bmwill@google.com> writes:
> On 12/12, Junio C Hamano wrote:
> ...
>> E.g. for input path "foo/bar/", the above loop runs zero times and
>> then ...
>>
>> > + /* Skip sequences of multiple path-separators */
>> > + while (offset < len && is_dir_sep(path->buf[len - 1]))
>> > + len--;
>>
>> ... the slash at the end is removed, leaving "foo/bar" in path.
>
> The way this is currently used I don't believe this scenario can happen
> (since input to this shouldn't have trailing slashes), but if others
> begin to use this function then yes, that is an implicit assumption.
OK.
>> > + /* Iterate over the remaining path components */
>> > + while (remaining.len > 0) {
>> > + get_next_component(&next, &remaining);
>> > +
>> > + if (next.len == 0) {
>> > + continue; /* empty component */
>> > + } else if (next.len == 1 && !strcmp(next.buf, ".")) {
>> > + continue; /* '.' component */
>> > + } else if (next.len == 2 && !strcmp(next.buf, "..")) {
>> > + /* '..' component; strip the last path component */
>> > + strip_last_component(&resolved);
>>
>> Wouldn't this let "resolved" eventually run out of the path
>> components to strip for a malformed input e.g. "/a/../../b"?
>
> As I understand it, that path is correct and would resolve to "/b".
That is OK on the traditional UNIX end.
I am not sure if we want to handle the "//host/share/$remaining" in
this codepath, though. If we do, then this is still an issue (IIRC,
somebody explained that we do not want to step into //host/share/
part when seeing ".."---we'd at least need to leave a NEEDSWORK
comment so that interested parties can later take a look into it.
^ permalink raw reply
* Re: [PATCH v3 4/4] real_path: have callers use real_pathdup and strbuf_realpath
From: Junio C Hamano @ 2016-12-12 23:47 UTC (permalink / raw)
To: Brandon Williams
Cc: git, sbeller, peff, jacob.keller, ramsay, tboegi, j6t, pclouds
In-Reply-To: <xmqqzik07pin.fsf@gitster.mtv.corp.google.com>
Junio C Hamano <gitster@pobox.com> writes:
> Brandon Williams <bmwill@google.com> writes:
>
>> Migrate callers of real_path() who duplicate the retern value to use
>> real_pathdup or strbuf_realpath.
>
> Looks good.
This has small non-textual conflicts with Stefan's embed^Wabsorption
topic; please holler if you spot my mismerge. Thanks.
^ permalink raw reply
* Re: [PATCH 1/3] update_unicode.sh: update the uniset repo if it exists
From: Beat Bolli @ 2016-12-12 23:50 UTC (permalink / raw)
To: git; +Cc: Torsten Bögershausen
In-Reply-To: <xmqqr35dm203.fsf@gitster.mtv.corp.google.com>
On 12.12.16 19:33, Junio C Hamano wrote:
> Torsten Bögershausen <tboegi@web.de> writes:
>
>> If I run ./update_unicode.sh on the latest master of
>> https://github.com/depp/uniset.git , commit
>> a5fac4a091857dd5429cc2d, I get a diff in unicode_width.h like
>> this:
>>
>> -{ 0x0300, 0x036F },
>>
>> +{ 768, 879 },
>>
>> IOW, all hex values are printed as decimal values.
>> Not a problem for the compiler, but for the human
>> to check the unicode tables.
>>
>> So I think we should "pin" the version of uniset.
>
> Sure, and I'd rather see the update-unicode.sh script moved
> somewhere in contrib/ while at it. Those who are interested in
> keeping up with the unicode standard are tiny minority of the
> developer population, and most of us would treat the built width
> table as the source (after all, that is what we ship).
>
> To be bluntly honest, I'd rather not to see "update-unicode.sh"
> download and build uniset at all. It's as if po/ hierarchy shipping
> with its own script to download and build msgmerge--that's madness.
> Needless to say, shipping the sources for uniset embedded in our
> project tree (either as a snapshot-fork or as a submodule) is even
> worse. Those who want to muck with po/ are expected to have
> msgmerge and friends. Why not expect the same for those who want to
> update the unicode width table?
>
> I'd rather see a written instruction telling which snapshot to get
> and from where to build and place on their $PATH in the README file,
> sitting next to the update-unicode.sh script in contrib/uniwidth/
> directory, for those who are interested in building the width table
> "from the source", and the update-unicode.sh script to assume that
> uniset is available.
>
OK. So please don't merge bb/unicode-9.0 to next yet; I'll prepare a
reroll following your description.
Torsten, is this alright with you?
Cheers, Beat
^ permalink raw reply
* [PATCH] t3600: slightly modernize style
From: Stefan Beller @ 2016-12-12 23:54 UTC (permalink / raw)
To: gitster; +Cc: git, Stefan Beller
Remove the space between redirection and file name.
Also remove unnecessary invocations of subshells, such as
(cd submod &&
echo X >untracked
) &&
as there is no point of having the shell for functional purposes.
In case of a single Git command use the `-C` option to let Git cd into
the directory.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
t/t3600-rm.sh | 122 ++++++++++++++++++++++++----------------------------------
1 file changed, 50 insertions(+), 72 deletions(-)
I came across this test script while developing the checkout series.
This motivated me to modernize the style while reading it.
The removal of spawning subshells for just one command could be argued to be
a performance gain as well, though I did not measure it.
Thanks,
Stefan
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 14f0edca2b..5e5a16c863 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -111,21 +111,21 @@ test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
'
test_expect_success '"rm" command printed' '
- echo frotz > test-file &&
+ echo frotz >test-file &&
git add test-file &&
git commit -m "add file for rm test" &&
- git rm test-file > rm-output &&
+ git rm test-file >rm-output &&
test $(grep "^rm " rm-output | wc -l) = 1 &&
rm -f test-file rm-output &&
git commit -m "remove file from rm test"
'
test_expect_success '"rm" command suppressed with --quiet' '
- echo frotz > test-file &&
+ echo frotz >test-file &&
git add test-file &&
git commit -m "add file for rm --quiet test" &&
- git rm --quiet test-file > rm-output &&
- test $(wc -l < rm-output) = 0 &&
+ git rm --quiet test-file >rm-output &&
+ test_must_be_empty rm-output &&
rm -f test-file rm-output &&
git commit -m "remove file from rm --quiet test"
'
@@ -221,7 +221,7 @@ test_expect_success 'Call "rm" from outside the work tree' '
mkdir repo &&
(cd repo &&
git init &&
- echo something > somefile &&
+ echo something >somefile &&
git add somefile &&
git commit -m "add a file" &&
(cd .. &&
@@ -287,7 +287,7 @@ test_expect_success 'rm removes empty submodules from work tree' '
git commit -m "add submodule" &&
git rm submod &&
test ! -e submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -298,7 +298,7 @@ test_expect_success 'rm removes removed submodule from index and .gitmodules' '
git submodule update &&
rm -rf submod &&
git rm submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -309,7 +309,7 @@ test_expect_success 'rm removes work tree of unmodified submodules' '
git submodule update &&
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -320,7 +320,7 @@ test_expect_success 'rm removes a submodule with a trailing /' '
git submodule update &&
git rm submod/ &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -335,17 +335,15 @@ test_expect_success 'rm succeeds when given a directory with a trailing /' '
test_expect_success 'rm of a populated submodule with different HEAD fails unless forced' '
git reset --hard &&
git submodule update &&
- (cd submod &&
- git checkout HEAD^
- ) &&
+ git -C submod checkout HEAD^ &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -418,34 +416,30 @@ test_expect_success 'rm issues a warning when section is not found in .gitmodule
test_expect_success 'rm of a populated submodule with modifications fails unless forced' '
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >empty
- ) &&
+ echo X >submod/empty &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated submodule with untracked files fails unless forced' '
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >untracked
- ) &&
+ echo X >submod/untracked &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -461,16 +455,12 @@ test_expect_success 'setup submodule conflict' '
git add nitfol &&
git commit -m "added nitfol 2" &&
git checkout -b conflict1 master &&
- (cd submod &&
- git fetch &&
- git checkout branch1
- ) &&
+ git -C submod fetch &&
+ git -C submod checkout branch1 &&
git add submod &&
git commit -m "submod 1" &&
git checkout -b conflict2 master &&
- (cd submod &&
- git checkout branch2
- ) &&
+ git -C submod checkout branch2 &&
git add submod &&
git commit -m "submod 2"
'
@@ -486,7 +476,7 @@ test_expect_success 'rm removes work tree of unmodified conflicted submodule' '
test_must_fail git merge conflict2 &&
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -494,18 +484,16 @@ test_expect_success 'rm of a conflicted populated submodule with different HEAD
git checkout conflict1 &&
git reset --hard &&
git submodule update &&
- (cd submod &&
- git checkout HEAD^
- ) &&
+ git -C submod checkout HEAD^ &&
test_must_fail git merge conflict2 &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -515,18 +503,16 @@ test_expect_success 'rm of a conflicted populated submodule with modifications f
git checkout conflict1 &&
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >empty
- ) &&
+ echo X >submod/empty &&
test_must_fail git merge conflict2 &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -536,18 +522,16 @@ test_expect_success 'rm of a conflicted populated submodule with untracked files
git checkout conflict1 &&
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >untracked
- ) &&
+ echo X >submod/untracked &&
test_must_fail git merge conflict2 &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -564,12 +548,12 @@ test_expect_success 'rm of a conflicted populated submodule with a .git director
test_must_fail git rm submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
test_must_fail git rm -f submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git merge --abort &&
rm -rf submod
@@ -581,7 +565,7 @@ test_expect_success 'rm of a conflicted unpopulated submodule succeeds' '
test_must_fail git merge conflict2 &&
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -597,12 +581,12 @@ test_expect_success 'rm of a populated submodule with a .git directory fails eve
test_must_fail git rm submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
test_must_fail git rm -f submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
rm -rf submod
'
@@ -629,58 +613,52 @@ test_expect_success 'setup subsubmodule' '
test_expect_success 'rm recursively removes work tree of unmodified submodules' '
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated nested submodule with different nested HEAD fails unless forced' '
git reset --hard &&
git submodule update --recursive &&
- (cd submod/subsubmod &&
- git checkout HEAD^
- ) &&
+ git -C submod/subsubmod checkout HEAD^ &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated nested submodule with nested modifications fails unless forced' '
git reset --hard &&
git submodule update --recursive &&
- (cd submod/subsubmod &&
- echo X >empty
- ) &&
+ echo X >submod/subsubmod/empty &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated nested submodule with nested untracked files fails unless forced' '
git reset --hard &&
git submodule update --recursive &&
- (cd submod/subsubmod &&
- echo X >untracked
- ) &&
+ echo X >submod/subsubmod/untracked &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -695,12 +673,12 @@ test_expect_success 'rm of a populated nested submodule with a nested .git direc
test_must_fail git rm submod &&
test -d submod &&
test -d submod/subsubmod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
test_must_fail git rm -f submod &&
test -d submod &&
test -d submod/subsubmod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
rm -rf submod
'
@@ -716,7 +694,7 @@ test_expect_success 'checking out a commit after submodule removal needs manual
echo "?? submod/" >expected &&
test_cmp expected actual &&
rm -rf submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual
'
--
2.11.0.rc2.55.g1345a36.dirty
^ permalink raw reply related
* Re: [PATCH v3 4/4] real_path: have callers use real_pathdup and strbuf_realpath
From: Stefan Beller @ 2016-12-12 23:58 UTC (permalink / raw)
To: Junio C Hamano
Cc: Brandon Williams, git@vger.kernel.org, Jeff King, Jacob Keller,
Ramsay Jones, Torsten Bögershausen, Johannes Sixt,
Duy Nguyen
In-Reply-To: <xmqqfuls7lri.fsf@gitster.mtv.corp.google.com>
On Mon, Dec 12, 2016 at 3:47 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> Brandon Williams <bmwill@google.com> writes:
>>
>>> Migrate callers of real_path() who duplicate the retern value to use
>>> real_pathdup or strbuf_realpath.
>>
>> Looks good.
>
> This has small non-textual conflicts with Stefan's embed^Wabsorption
> topic; please holler if you spot my mismerge. Thanks.
>
5f6a003727 (Merge branch 'bw/realpath-wo-chdir' into jch)
looks good to me.
^ permalink raw reply
* Re: [PATCHv2 5/7] versioncmp: cope with common part overlapping with prerelease suffix
From: SZEDER Gábor @ 2016-12-13 0:27 UTC (permalink / raw)
To: Junio C Hamano
Cc: Jeff King, Nguyễn Thái Ngọc Duy, Leho Kraav, git
In-Reply-To: <xmqqshps96ti.fsf@gitster.mtv.corp.google.com>
On Mon, Dec 12, 2016 at 10:27 PM, Junio C Hamano <gitster@pobox.com> wrote:
> SZEDER Gábor <szeder.dev@gmail.com> writes:
>
>> diff --git a/versioncmp.c b/versioncmp.c
>> index a55c23ad5..f86ac562e 100644
>> --- a/versioncmp.c
>> +++ b/versioncmp.c
>> @@ -26,12 +26,15 @@ static int initialized;
>>
>> /*
>> * off is the offset of the first different character in the two strings
>> - * s1 and s2. If either s1 or s2 contains a prerelease suffix starting
>> - * at that offset, it will be forced to be on top.
>> + * s1 and s2. If either s1 or s2 contains a prerelease suffix containing
>> + * that offset, then that string will be forced to be on top.
>> *
>> - * If both s1 and s2 contain a (different) suffix at that position,
>> + * If both s1 and s2 contain a (different) suffix around that position,
>> * their order is determined by the order of those two suffixes in the
>> * configuration.
>> + * If any of the strings contains more than one different suffixes around
>> + * that position, then that string is sorted according to the contained
>> + * suffix which comes first in the configuration.
>> *
>> * Return non-zero if *diff contains the return value for versioncmp()
>> */
>> @@ -44,10 +47,21 @@ static int swap_prereleases(const char *s1,
>>
>> for (i = 0; i < prereleases->nr; i++) {
>> const char *suffix = prereleases->items[i].string;
>> - if (i1 == -1 && starts_with(s1 + off, suffix))
>> - i1 = i;
>> - if (i2 == -1 && starts_with(s2 + off, suffix))
>> - i2 = i;
>> + int j, start, suffix_len = strlen(suffix);
>> + if (suffix_len < off)
>> + start = off - suffix_len + 1;
>> + else
>> + start = 0;
>
> Now that this function has to rewind the beginning of the comparison
> earlier than the given 'off', it makes me wonder if it still makes
> sense for the caller to compute it in the first place.
The caller has to compute it anyway, because it must deal with all the
cases when the two compared tagnames are not reordered based on their
(prerelease)suffix.
^ permalink raw reply
* Re: [PATCH v3 4/4] real_path: have callers use real_pathdup and strbuf_realpath
From: Brandon Williams @ 2016-12-13 1:15 UTC (permalink / raw)
To: Stefan Beller
Cc: Junio C Hamano, git@vger.kernel.org, Jeff King, Jacob Keller,
Ramsay Jones, Torsten Bögershausen, Johannes Sixt,
Duy Nguyen
In-Reply-To: <CAGZ79kbYAyGwTb7AkymoaMo+TPGVRiv8kn00fXGS=S_ZVFG0Jw@mail.gmail.com>
On 12/12, Stefan Beller wrote:
> On Mon, Dec 12, 2016 at 3:47 PM, Junio C Hamano <gitster@pobox.com> wrote:
> > Junio C Hamano <gitster@pobox.com> writes:
> >
> >> Brandon Williams <bmwill@google.com> writes:
> >>
> >>> Migrate callers of real_path() who duplicate the retern value to use
> >>> real_pathdup or strbuf_realpath.
> >>
> >> Looks good.
> >
> > This has small non-textual conflicts with Stefan's embed^Wabsorption
> > topic; please holler if you spot my mismerge. Thanks.
> >
>
> 5f6a003727 (Merge branch 'bw/realpath-wo-chdir' into jch)
> looks good to me.
Looks good to me as well.
--
Brandon Williams
^ permalink raw reply
* [PATCH 0/6] git-rm absorbs submodule git directory before deletion
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
The "checkout --recurse-submodules" series got too large to comfortably send
it out for review, so I had to break it up into smaller series'; this is the
first subseries, but it makes sense on its own.
This series teaches git-rm to absorb the git directory of a submodule instead
of failing and complaining about the git directory preventing deletion.
It applies on origin/sb/submodule-embed-gitdir.
Any feedback welcome!
Thanks,
Stefan
Stefan Beller (6):
submodule.h: add extern keyword to functions
submodule: modernize ok_to_remove_submodule to use argv_array
submodule: add flags to ok_to_remove_submodule
ok_to_remove_submodule: absorb the submodule git dir
t3600: slightly modernize style
rm: add absorb a submodules git dir before deletion
builtin/rm.c | 21 +++-----
cache.h | 2 +
entry.c | 5 ++
submodule.c | 77 +++++++++++++++++++++++-----
submodule.h | 64 ++++++++++++++---------
t/t3600-rm.sh | 159 +++++++++++++++++++++++----------------------------------
6 files changed, 182 insertions(+), 146 deletions(-)
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply
* [PATCH 2/6] submodule: modernize ok_to_remove_submodule to use argv_array
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
In-Reply-To: <20161213014055.14268-1-sbeller@google.com>
Instead of constructing the NULL terminated array ourselves, we
should make use of the argv_array infrastructure.
While at it, adapt the error messages to reflect the actual invocation.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
submodule.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/submodule.c b/submodule.c
index 45ccfb7ab4..9f0b544ebe 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1023,13 +1023,6 @@ int ok_to_remove_submodule(const char *path)
{
ssize_t len;
struct child_process cp = CHILD_PROCESS_INIT;
- const char *argv[] = {
- "status",
- "--porcelain",
- "-u",
- "--ignore-submodules=none",
- NULL,
- };
struct strbuf buf = STRBUF_INIT;
int ok_to_remove = 1;
@@ -1039,14 +1032,15 @@ int ok_to_remove_submodule(const char *path)
if (!submodule_uses_gitfile(path))
return 0;
- cp.argv = argv;
+ argv_array_pushl(&cp.args, "status", "--porcelain", "-u",
+ "--ignore-submodules=none", NULL);
prepare_submodule_repo_env(&cp.env_array);
cp.git_cmd = 1;
cp.no_stdin = 1;
cp.out = -1;
cp.dir = path;
if (start_command(&cp))
- die("Could not run 'git status --porcelain -uall --ignore-submodules=none' in submodule %s", path);
+ die(_("could not run 'git status --porcelain -u --ignore-submodules=none' in submodule %s"), path);
len = strbuf_read(&buf, cp.out, 1024);
if (len > 2)
@@ -1054,7 +1048,7 @@ int ok_to_remove_submodule(const char *path)
close(cp.out);
if (finish_command(&cp))
- die("'git status --porcelain -uall --ignore-submodules=none' failed in submodule %s", path);
+ die(_("'git status --porcelain -u --ignore-submodules=none' failed in submodule %s"), path);
strbuf_release(&buf);
return ok_to_remove;
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply related
* [PATCH 4/6] ok_to_remove_submodule: absorb the submodule git dir
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
In-Reply-To: <20161213014055.14268-1-sbeller@google.com>
When deciding if a submodule can be deleted a major
reason to say no is the git directory of the submodule
being contained in the submodules working directory.
Instead of failing migrate the git directory into the
superproject and proceed with the other checks.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
submodule.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/submodule.c b/submodule.c
index 2d13744b06..e42efa2337 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1026,11 +1026,22 @@ int ok_to_remove_submodule(const char *path, unsigned flags)
struct strbuf buf = STRBUF_INIT;
int ok_to_remove = 1;
+ /* Is it there? */
if (!file_exists(path) || is_empty_dir(path))
return 1;
- if (!submodule_uses_gitfile(path))
- return 0;
+ /* Does it have a .git directory? */
+ if (!submodule_uses_gitfile(path)) {
+ absorb_git_dir_into_superproject("", path,
+ ABSORB_GITDIR_RECURSE_SUBMODULES);
+
+ /*
+ * We should be using a gitfile by now. Let's double
+ * check as losing the git dir would be fatal.
+ */
+ if (!submodule_uses_gitfile(path))
+ return 0;
+ }
argv_array_pushl(&cp.args, "status", "--porcelain",
"--ignore-submodules=none", NULL);
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply related
* [PATCH 1/6] submodule.h: add extern keyword to functions
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
In-Reply-To: <20161213014055.14268-1-sbeller@google.com>
As the upcoming series will add a lot of functions to the submodule
header, let's first make the header consistent to the rest of the project
by adding the extern keyword to functions.
As per the CodingGuidelines we try to stay below 80 characters per line,
so adapt all those functions to stay below 80 characters that are already
using more than one line. Those function using just one line are better
kept in one line than breaking them up into multiple lines just for the
goal of staying below the character limit as it makes grepping
for functions easier if they are one liners.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
submodule.h | 55 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 30 insertions(+), 25 deletions(-)
diff --git a/submodule.h b/submodule.h
index 6229054b99..61fb610749 100644
--- a/submodule.h
+++ b/submodule.h
@@ -29,50 +29,55 @@ struct submodule_update_strategy {
};
#define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}
-int is_staging_gitmodules_ok(void);
-int update_path_in_gitmodules(const char *oldpath, const char *newpath);
-int remove_path_from_gitmodules(const char *path);
-void stage_updated_gitmodules(void);
-void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
+extern int is_staging_gitmodules_ok(void);
+extern int update_path_in_gitmodules(const char *oldpath, const char *newpath);
+extern int remove_path_from_gitmodules(const char *path);
+extern void stage_updated_gitmodules(void);
+extern void set_diffopt_flags_from_submodule_config(struct diff_options *,
const char *path);
-int submodule_config(const char *var, const char *value, void *cb);
-void gitmodules_config(void);
-int parse_submodule_update_strategy(const char *value,
+extern int submodule_config(const char *var, const char *value, void *cb);
+extern void gitmodules_config(void);
+extern int parse_submodule_update_strategy(const char *value,
struct submodule_update_strategy *dst);
-const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
-void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
-void show_submodule_summary(FILE *f, const char *path,
+extern const char *submodule_strategy_to_string(const struct submodule_update_strategy *s);
+extern void handle_ignore_submodules_arg(struct diff_options *, const char *);
+extern void show_submodule_summary(FILE *f, const char *path,
const char *line_prefix,
struct object_id *one, struct object_id *two,
unsigned dirty_submodule, const char *meta,
const char *del, const char *add, const char *reset);
-void show_submodule_inline_diff(FILE *f, const char *path,
+extern void show_submodule_inline_diff(FILE *f, const char *path,
const char *line_prefix,
struct object_id *one, struct object_id *two,
unsigned dirty_submodule, const char *meta,
const char *del, const char *add, const char *reset,
const struct diff_options *opt);
-void set_config_fetch_recurse_submodules(int value);
-void check_for_new_submodule_commits(unsigned char new_sha1[20]);
-int fetch_populated_submodules(const struct argv_array *options,
+extern void set_config_fetch_recurse_submodules(int value);
+extern void check_for_new_submodule_commits(unsigned char new_sha1[20]);
+extern int fetch_populated_submodules(const struct argv_array *options,
const char *prefix, int command_line_option,
int quiet, int max_parallel_jobs);
-unsigned is_submodule_modified(const char *path, int ignore_untracked);
-int submodule_uses_gitfile(const char *path);
-int ok_to_remove_submodule(const char *path);
-int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
- const unsigned char a[20], const unsigned char b[20], int search);
-int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name,
- struct string_list *needs_pushing);
-int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
-int parallel_submodules(void);
+extern unsigned is_submodule_modified(const char *path, int ignore_untracked);
+extern int submodule_uses_gitfile(const char *path);
+extern int ok_to_remove_submodule(const char *path);
+extern int merge_submodule(unsigned char result[20], const char *path,
+ const unsigned char base[20],
+ const unsigned char a[20],
+ const unsigned char b[20], int search);
+extern int find_unpushed_submodules(unsigned char new_sha1[20],
+ const char *remotes_name,
+ struct string_list *needs_pushing);
+extern int push_unpushed_submodules(unsigned char new_sha1[20],
+ const char *remotes_name);
+extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
+extern int parallel_submodules(void);
/*
* Prepare the "env_array" parameter of a "struct child_process" for executing
* a submodule by clearing any repo-specific envirionment variables, but
* retaining any config in the environment.
*/
-void prepare_submodule_repo_env(struct argv_array *out);
+extern void prepare_submodule_repo_env(struct argv_array *out);
#define ABSORB_GITDIR_RECURSE_SUBMODULES (1<<0)
extern void absorb_git_dir_into_superproject(const char *prefix,
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply related
* [PATCH 3/6] submodule: add flags to ok_to_remove_submodule
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
In-Reply-To: <20161213014055.14268-1-sbeller@google.com>
In different contexts the question whether deleting a submodule is ok
to remove may be answered differently.
In 293ab15eea (submodule: teach rm to remove submodules unless they
contain a git directory, 2012-09-26) a case was made that we can safely
ignore ignored untracked files for removal as we explicitely ask for the
removal of the submodule.
In a later patch we want to remove submodules even when the user doesn't
explicitly ask for it (e.g. checking out a tree-ish in which the submodule
doesn't exist). In that case we want to be more careful when it comes
to deletion of untracked files. As of this patch it is unclear how this
will be implemented exactly, so we'll offer flags in which the caller
can specify how the different untracked files ought to be handled.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
builtin/rm.c | 3 ++-
submodule.c | 23 +++++++++++++++++++----
submodule.h | 5 ++++-
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/builtin/rm.c b/builtin/rm.c
index 3f3e24eb36..fdd7183f61 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -187,7 +187,8 @@ static int check_local_mod(struct object_id *head, int index_only)
*/
if (ce_match_stat(ce, &st, 0) ||
(S_ISGITLINK(ce->ce_mode) &&
- !ok_to_remove_submodule(ce->name)))
+ !ok_to_remove_submodule(ce->name,
+ SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED)))
local_changes = 1;
/*
diff --git a/submodule.c b/submodule.c
index 9f0b544ebe..2d13744b06 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1019,7 +1019,7 @@ int submodule_uses_gitfile(const char *path)
return 1;
}
-int ok_to_remove_submodule(const char *path)
+int ok_to_remove_submodule(const char *path, unsigned flags)
{
ssize_t len;
struct child_process cp = CHILD_PROCESS_INIT;
@@ -1032,15 +1032,27 @@ int ok_to_remove_submodule(const char *path)
if (!submodule_uses_gitfile(path))
return 0;
- argv_array_pushl(&cp.args, "status", "--porcelain", "-u",
+ argv_array_pushl(&cp.args, "status", "--porcelain",
"--ignore-submodules=none", NULL);
+
+ if (flags & SUBMODULE_REMOVAL_IGNORE_UNTRACKED)
+ argv_array_push(&cp.args, "-uno");
+ else
+ argv_array_push(&cp.args, "-uall");
+
+ if (!(flags & SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED))
+ argv_array_push(&cp.args, "--ignored");
+
prepare_submodule_repo_env(&cp.env_array);
cp.git_cmd = 1;
cp.no_stdin = 1;
cp.out = -1;
cp.dir = path;
if (start_command(&cp))
- die(_("could not run 'git status --porcelain -u --ignore-submodules=none' in submodule %s"), path);
+ die(_("could not run 'git status --porcelain --ignore-submodules=none %s %s' in submodule '%s'"),
+ (flags & SUBMODULE_REMOVAL_IGNORE_UNTRACKED) ? "-uno" : "-uall",
+ (!(flags & SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED)) ? "--ignored" : "",
+ path);
len = strbuf_read(&buf, cp.out, 1024);
if (len > 2)
@@ -1048,7 +1060,10 @@ int ok_to_remove_submodule(const char *path)
close(cp.out);
if (finish_command(&cp))
- die(_("'git status --porcelain -u --ignore-submodules=none' failed in submodule %s"), path);
+ die(_("'git status --porcelain --ignore-submodules=none %s %s' failed in submodule '%s'"),
+ (flags & SUBMODULE_REMOVAL_IGNORE_UNTRACKED) ? "-uno" : "-uall",
+ (!(flags & SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED)) ? "--ignored" : "",
+ path);
strbuf_release(&buf);
return ok_to_remove;
diff --git a/submodule.h b/submodule.h
index 61fb610749..3ed3aa479a 100644
--- a/submodule.h
+++ b/submodule.h
@@ -59,7 +59,10 @@ extern int fetch_populated_submodules(const struct argv_array *options,
int quiet, int max_parallel_jobs);
extern unsigned is_submodule_modified(const char *path, int ignore_untracked);
extern int submodule_uses_gitfile(const char *path);
-extern int ok_to_remove_submodule(const char *path);
+
+#define SUBMODULE_REMOVAL_IGNORE_UNTRACKED (1<<0)
+#define SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED (1<<1)
+extern int ok_to_remove_submodule(const char *path, unsigned flags);
extern int merge_submodule(unsigned char result[20], const char *path,
const unsigned char base[20],
const unsigned char a[20],
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply related
* [PATCH 6/6] rm: add absorb a submodules git dir before deletion
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
In-Reply-To: <20161213014055.14268-1-sbeller@google.com>
When deleting a submodule we need to keep the actual git directory around,
such that we do not lose local changes in there and at a later checkout
of the submodule we don't need to clone it again.
Implement `depopulate_submodule`, that migrates the git directory before
deletion of a submodule and afterwards the equivalent of "rm -rf", which
is already found in entry.c, so expose that and for clarity add a suffix
"_or_dir" to it.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
builtin/rm.c | 18 ++++++------------
cache.h | 2 ++
entry.c | 5 +++++
submodule.c | 31 +++++++++++++++++++++++++++++++
submodule.h | 6 ++++++
t/t3600-rm.sh | 41 ++++++++++++++++-------------------------
6 files changed, 66 insertions(+), 37 deletions(-)
diff --git a/builtin/rm.c b/builtin/rm.c
index fdd7183f61..f8c5e9b6c6 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -400,18 +400,12 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
continue;
}
} else {
- strbuf_reset(&buf);
- strbuf_addstr(&buf, path);
- if (!remove_dir_recursively(&buf, 0)) {
- removed = 1;
- if (!remove_path_from_gitmodules(path))
- gitmodules_modified = 1;
- strbuf_release(&buf);
- continue;
- } else if (!file_exists(path))
- /* Submodule was removed by user */
- if (!remove_path_from_gitmodules(path))
- gitmodules_modified = 1;
+ if (file_exists(path))
+ depopulate_submodule(path);
+ removed = 1;
+ if (!remove_path_from_gitmodules(path))
+ gitmodules_modified = 1;
+ continue;
/* Fallthrough and let remove_path() fail. */
}
}
diff --git a/cache.h b/cache.h
index a50a61a197..b645ca2f9a 100644
--- a/cache.h
+++ b/cache.h
@@ -2018,4 +2018,6 @@ void sleep_millisec(int millisec);
*/
void safe_create_dir(const char *dir, int share);
+extern void remove_directory_or_die(struct strbuf *path);
+
#endif /* CACHE_H */
diff --git a/entry.c b/entry.c
index c6eea240b6..02c4ac9f22 100644
--- a/entry.c
+++ b/entry.c
@@ -73,6 +73,11 @@ static void remove_subtree(struct strbuf *path)
die_errno("cannot rmdir '%s'", path->buf);
}
+void remove_directory_or_die(struct strbuf *path)
+{
+ remove_subtree(path);
+}
+
static int create_file(const char *path, unsigned int mode)
{
mode = (mode & 0100) ? 0777 : 0666;
diff --git a/submodule.c b/submodule.c
index e42efa2337..3770ecb7b9 100644
--- a/submodule.c
+++ b/submodule.c
@@ -308,6 +308,37 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f,
strbuf_release(&sb);
}
+void depopulate_submodule(const char *path)
+{
+ struct strbuf pathbuf = STRBUF_INIT;
+ char *dot_git = xstrfmt("%s/.git", path);
+
+ /* Is it populated? */
+ if (!resolve_gitdir(dot_git))
+ goto out;
+
+ /* Does it have a .git directory? */
+ if (!submodule_uses_gitfile(path)) {
+ absorb_git_dir_into_superproject("", path,
+ ABSORB_GITDIR_RECURSE_SUBMODULES);
+
+ if (!submodule_uses_gitfile(path)) {
+ /*
+ * We should be using a gitfile by now. Let's double
+ * check as losing the git dir would be fatal.
+ */
+ die("BUG: could not absorb git directory for '%s'", path);
+ }
+ }
+
+ strbuf_addstr(&pathbuf, path);
+ remove_directory_or_die(&pathbuf);
+
+out:
+ strbuf_release(&pathbuf);
+ free(dot_git);
+}
+
/* Helper function to display the submodule header line prior to the full
* summary output. If it can locate the submodule objects directory it will
* attempt to lookup both the left and right commits and put them into the
diff --git a/submodule.h b/submodule.h
index 3ed3aa479a..516e377a12 100644
--- a/submodule.h
+++ b/submodule.h
@@ -53,6 +53,12 @@ extern void show_submodule_inline_diff(FILE *f, const char *path,
const char *del, const char *add, const char *reset,
const struct diff_options *opt);
extern void set_config_fetch_recurse_submodules(int value);
+
+/*
+ * Removes a submodule from a given path. When the submodule contains its
+ * git directory instead of a gitlink, migrate that first into the superproject.
+ */
+extern void depopulate_submodule(const char *path);
extern void check_for_new_submodule_commits(unsigned char new_sha1[20]);
extern int fetch_populated_submodules(const struct argv_array *options,
const char *prefix, int command_line_option,
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 5e5a16c863..5aa6db584c 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -569,26 +569,22 @@ test_expect_success 'rm of a conflicted unpopulated submodule succeeds' '
test_cmp expect actual
'
-test_expect_success 'rm of a populated submodule with a .git directory fails even when forced' '
+test_expect_success 'rm of a populated submodule with a .git directory migrates git dir' '
git checkout -f master &&
git reset --hard &&
git submodule update &&
(cd submod &&
rm .git &&
cp -R ../.git/modules/sub .git &&
- GIT_WORK_TREE=. git config --unset core.worktree
+ GIT_WORK_TREE=. git config --unset core.worktree &&
+ rm -r ../.git/modules/sub
) &&
- test_must_fail git rm submod &&
- test -d submod &&
- test -d submod/.git &&
- git status -s -uno --ignore-submodules=none >actual &&
- ! test -s actual &&
- test_must_fail git rm -f submod &&
- test -d submod &&
- test -d submod/.git &&
+ git rm submod 2>output.err &&
+ ! test -d submod &&
+ ! test -d submod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- ! test -s actual &&
- rm -rf submod
+ test -s actual &&
+ test_i18ngrep Migrating output.err
'
cat >expect.deepmodified <<EOF
@@ -667,27 +663,22 @@ test_expect_success 'rm of a populated nested submodule with a nested .git direc
git submodule update --recursive &&
(cd submod/subsubmod &&
rm .git &&
- cp -R ../../.git/modules/sub/modules/sub .git &&
+ mv ../../.git/modules/sub/modules/sub .git &&
GIT_WORK_TREE=. git config --unset core.worktree
) &&
- test_must_fail git rm submod &&
- test -d submod &&
- test -d submod/subsubmod/.git &&
- git status -s -uno --ignore-submodules=none >actual &&
- ! test -s actual &&
- test_must_fail git rm -f submod &&
- test -d submod &&
- test -d submod/subsubmod/.git &&
+ git rm submod 2>output.err &&
+ ! test -d submod &&
+ ! test -d submod/subsubmod/.git &&
git status -s -uno --ignore-submodules=none >actual &&
- ! test -s actual &&
- rm -rf submod
+ test -s actual &&
+ test_i18ngrep Migrating output.err
'
test_expect_success 'checking out a commit after submodule removal needs manual updates' '
- git commit -m "submodule removal" submod &&
+ git commit -m "submodule removal" submod .gitmodules &&
git checkout HEAD^ &&
git submodule update &&
- git checkout -q HEAD^ 2>actual &&
+ git checkout -q HEAD^ &&
git checkout -q master 2>actual &&
test_i18ngrep "^warning: unable to rmdir submod:" actual &&
git status -s submod >actual &&
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply related
* [PATCH 5/6] t3600: slightly modernize style
From: Stefan Beller @ 2016-12-13 1:40 UTC (permalink / raw)
To: gitster; +Cc: git, David.Turner, bmwill, Stefan Beller
In-Reply-To: <20161213014055.14268-1-sbeller@google.com>
Remove the space between redirection and file name.
Also remove unnecessary invocations of subshells, such as
(cd submod &&
echo X >untracked
) &&
as there is no point of having the shell for functional purposes.
In case of a single Git command use the `-C` option to let Git cd into
the directory.
Signed-off-by: Stefan Beller <sbeller@google.com>
---
t/t3600-rm.sh | 122 ++++++++++++++++++++++++----------------------------------
1 file changed, 50 insertions(+), 72 deletions(-)
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 14f0edca2b..5e5a16c863 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -111,21 +111,21 @@ test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
'
test_expect_success '"rm" command printed' '
- echo frotz > test-file &&
+ echo frotz >test-file &&
git add test-file &&
git commit -m "add file for rm test" &&
- git rm test-file > rm-output &&
+ git rm test-file >rm-output &&
test $(grep "^rm " rm-output | wc -l) = 1 &&
rm -f test-file rm-output &&
git commit -m "remove file from rm test"
'
test_expect_success '"rm" command suppressed with --quiet' '
- echo frotz > test-file &&
+ echo frotz >test-file &&
git add test-file &&
git commit -m "add file for rm --quiet test" &&
- git rm --quiet test-file > rm-output &&
- test $(wc -l < rm-output) = 0 &&
+ git rm --quiet test-file >rm-output &&
+ test_must_be_empty rm-output &&
rm -f test-file rm-output &&
git commit -m "remove file from rm --quiet test"
'
@@ -221,7 +221,7 @@ test_expect_success 'Call "rm" from outside the work tree' '
mkdir repo &&
(cd repo &&
git init &&
- echo something > somefile &&
+ echo something >somefile &&
git add somefile &&
git commit -m "add a file" &&
(cd .. &&
@@ -287,7 +287,7 @@ test_expect_success 'rm removes empty submodules from work tree' '
git commit -m "add submodule" &&
git rm submod &&
test ! -e submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -298,7 +298,7 @@ test_expect_success 'rm removes removed submodule from index and .gitmodules' '
git submodule update &&
rm -rf submod &&
git rm submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -309,7 +309,7 @@ test_expect_success 'rm removes work tree of unmodified submodules' '
git submodule update &&
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -320,7 +320,7 @@ test_expect_success 'rm removes a submodule with a trailing /' '
git submodule update &&
git rm submod/ &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -335,17 +335,15 @@ test_expect_success 'rm succeeds when given a directory with a trailing /' '
test_expect_success 'rm of a populated submodule with different HEAD fails unless forced' '
git reset --hard &&
git submodule update &&
- (cd submod &&
- git checkout HEAD^
- ) &&
+ git -C submod checkout HEAD^ &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -418,34 +416,30 @@ test_expect_success 'rm issues a warning when section is not found in .gitmodule
test_expect_success 'rm of a populated submodule with modifications fails unless forced' '
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >empty
- ) &&
+ echo X >submod/empty &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated submodule with untracked files fails unless forced' '
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >untracked
- ) &&
+ echo X >submod/untracked &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -461,16 +455,12 @@ test_expect_success 'setup submodule conflict' '
git add nitfol &&
git commit -m "added nitfol 2" &&
git checkout -b conflict1 master &&
- (cd submod &&
- git fetch &&
- git checkout branch1
- ) &&
+ git -C submod fetch &&
+ git -C submod checkout branch1 &&
git add submod &&
git commit -m "submod 1" &&
git checkout -b conflict2 master &&
- (cd submod &&
- git checkout branch2
- ) &&
+ git -C submod checkout branch2 &&
git add submod &&
git commit -m "submod 2"
'
@@ -486,7 +476,7 @@ test_expect_success 'rm removes work tree of unmodified conflicted submodule' '
test_must_fail git merge conflict2 &&
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -494,18 +484,16 @@ test_expect_success 'rm of a conflicted populated submodule with different HEAD
git checkout conflict1 &&
git reset --hard &&
git submodule update &&
- (cd submod &&
- git checkout HEAD^
- ) &&
+ git -C submod checkout HEAD^ &&
test_must_fail git merge conflict2 &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -515,18 +503,16 @@ test_expect_success 'rm of a conflicted populated submodule with modifications f
git checkout conflict1 &&
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >empty
- ) &&
+ echo X >submod/empty &&
test_must_fail git merge conflict2 &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual &&
test_must_fail git config -f .gitmodules submodule.sub.url &&
test_must_fail git config -f .gitmodules submodule.sub.path
@@ -536,18 +522,16 @@ test_expect_success 'rm of a conflicted populated submodule with untracked files
git checkout conflict1 &&
git reset --hard &&
git submodule update &&
- (cd submod &&
- echo X >untracked
- ) &&
+ echo X >submod/untracked &&
test_must_fail git merge conflict2 &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -564,12 +548,12 @@ test_expect_success 'rm of a conflicted populated submodule with a .git director
test_must_fail git rm submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
test_must_fail git rm -f submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.conflict actual &&
git merge --abort &&
rm -rf submod
@@ -581,7 +565,7 @@ test_expect_success 'rm of a conflicted unpopulated submodule succeeds' '
test_must_fail git merge conflict2 &&
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -597,12 +581,12 @@ test_expect_success 'rm of a populated submodule with a .git directory fails eve
test_must_fail git rm submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
test_must_fail git rm -f submod &&
test -d submod &&
test -d submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
rm -rf submod
'
@@ -629,58 +613,52 @@ test_expect_success 'setup subsubmodule' '
test_expect_success 'rm recursively removes work tree of unmodified submodules' '
git rm submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated nested submodule with different nested HEAD fails unless forced' '
git reset --hard &&
git submodule update --recursive &&
- (cd submod/subsubmod &&
- git checkout HEAD^
- ) &&
+ git -C submod/subsubmod checkout HEAD^ &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated nested submodule with nested modifications fails unless forced' '
git reset --hard &&
git submodule update --recursive &&
- (cd submod/subsubmod &&
- echo X >empty
- ) &&
+ echo X >submod/subsubmod/empty &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
test_expect_success 'rm of a populated nested submodule with nested untracked files fails unless forced' '
git reset --hard &&
git submodule update --recursive &&
- (cd submod/subsubmod &&
- echo X >untracked
- ) &&
+ echo X >submod/subsubmod/untracked &&
test_must_fail git rm submod &&
test -d submod &&
test -f submod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect.modified actual &&
git rm -f submod &&
test ! -d submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
test_cmp expect actual
'
@@ -695,12 +673,12 @@ test_expect_success 'rm of a populated nested submodule with a nested .git direc
test_must_fail git rm submod &&
test -d submod &&
test -d submod/subsubmod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
test_must_fail git rm -f submod &&
test -d submod &&
test -d submod/subsubmod/.git &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual &&
rm -rf submod
'
@@ -716,7 +694,7 @@ test_expect_success 'checking out a commit after submodule removal needs manual
echo "?? submod/" >expected &&
test_cmp expected actual &&
rm -rf submod &&
- git status -s -uno --ignore-submodules=none > actual &&
+ git status -s -uno --ignore-submodules=none >actual &&
! test -s actual
'
--
2.11.0.rc2.35.g7af3268
^ permalink raw reply related
* Re: [PATCH 6/6] rm: add absorb a submodules git dir before deletion
From: brian m. carlson @ 2016-12-13 3:28 UTC (permalink / raw)
To: Stefan Beller; +Cc: gitster, git, David.Turner, bmwill
In-Reply-To: <20161213014055.14268-7-sbeller@google.com>
[-- Attachment #1: Type: text/plain, Size: 915 bytes --]
On Mon, Dec 12, 2016 at 05:40:55PM -0800, Stefan Beller wrote:
> When deleting a submodule we need to keep the actual git directory around,
> such that we do not lose local changes in there and at a later checkout
> of the submodule we don't need to clone it again.
>
> Implement `depopulate_submodule`, that migrates the git directory before
> deletion of a submodule and afterwards the equivalent of "rm -rf", which
> is already found in entry.c, so expose that and for clarity add a suffix
> "_or_dir" to it.
I think you might have meant "_or_die" here.
Other than that, I didn't see anything that stuck out to me in this
series as obviously wrong or broken, but this isn't an area of the code
I'm super familiar with.
--
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | https://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: https://keybase.io/bk2204
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 868 bytes --]
^ permalink raw reply
* Re: [PATCH 1/3] update_unicode.sh: update the uniset repo if it exists
From: Torsten Bögershausen @ 2016-12-13 6:16 UTC (permalink / raw)
To: Beat Bolli, git
In-Reply-To: <954eed6b-c899-4f4c-eb3d-2b6d2ff4385d@drbeat.li>
>> Sure, and I'd rather see the update-unicode.sh script moved
>> somewhere in contrib/ while at it. Those who are interested in
>> keeping up with the unicode standard are tiny minority of the
>> developer population, and most of us would treat the built width
>> table as the source (after all, that is what we ship).
>>
>> To be bluntly honest, I'd rather not to see "update-unicode.sh"
>> download and build uniset at all. It's as if po/ hierarchy shipping
>> with its own script to download and build msgmerge--that's madness.
>> Needless to say, shipping the sources for uniset embedded in our
>> project tree (either as a snapshot-fork or as a submodule) is even
>> worse. Those who want to muck with po/ are expected to have
>> msgmerge and friends. Why not expect the same for those who want to
>> update the unicode width table?
>>
>> I'd rather see a written instruction telling which snapshot to get
>> and from where to build and place on their $PATH in the README file,
>> sitting next to the update-unicode.sh script in contrib/uniwidth/
>> directory, for those who are interested in building the width table
>> "from the source", and the update-unicode.sh script to assume that
>> uniset is available.
OK with the contrib - that's an improvement.
About the instructions how to download and compile:
(we don't need to change the $PATH, do we ?)
I don't know.
The typical instructions I have seen are a sequence of shell commands
to be executed, which hopefully simply work by doing "copy-and-paste".
I find this error-prone, as you you may loose the last character while
moving the mouse, or don't check the error message or return codes.
Having a pre-baked shell script, which does use "&&" is in that way more
attractive,
and the README can be as simple as run "update-unicode.sh" and that's it.
uniset is a small project and where should we put it ?
a) inside the Git tree?
b) /tmp ?
c) into the $HOME directory ?
d) /usr/local
a) is quick and dirty
b) probably OK
c) Not sure about tha
d) Needs super user rights
Can we try to find a good place ?
"contrib/uniwidth/" may be different to find, how about contrib/update-unicode ?
> OK. So please don't merge bb/unicode-9.0 to next yet; I'll prepare a
> reroll following your description.
>
> Torsten, is this alright with you?
sure
> Cheers, Beat
^ permalink raw reply
* Re: [PATCHv2 5/7] versioncmp: cope with common part overlapping with prerelease suffix
From: Junio C Hamano @ 2016-12-13 6:39 UTC (permalink / raw)
To: SZEDER Gábor
Cc: Jeff King, Nguyễn Thái Ngọc Duy, Leho Kraav, git
In-Reply-To: <CAM0VKjnPdt3keodXRFNit9=WKeY330N4T2t_dJuArgch7L6BNg@mail.gmail.com>
SZEDER Gábor <szeder.dev@gmail.com> writes:
>>> - if (i1 == -1 && starts_with(s1 + off, suffix))
>>> - i1 = i;
>>> - if (i2 == -1 && starts_with(s2 + off, suffix))
>>> - i2 = i;
>>> + int j, start, suffix_len = strlen(suffix);
>>> + if (suffix_len < off)
>>> + start = off - suffix_len + 1;
>>> + else
>>> + start = 0;
>>
>> Now that this function has to rewind the beginning of the comparison
>> earlier than the given 'off', it makes me wonder if it still makes
>> sense for the caller to compute it in the first place.
>
> The caller has to compute it anyway, because it must deal with all the
> cases when the two compared tagnames are not reordered based on their
> (prerelease)suffix.
Sure.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox