From: Stefan Beller <hidden> Date: 2016-08-04 19:52:12
Currently when cloning a superproject with --recursive and --reference
only the superproject learns about its alternates. The submodules are
cloned independently, which may incur lots of network costs.
Assume that the reference repository has the submodules at the same
paths as the to-be-cloned submodule and try to setup alternates from
there.
Some submodules in the referenced superproject may not be there,
(they are just not initialized/cloned/checked out), which yields
an error for now. In future work we may want to soften the alternate
check and not die in the clone when one of the given alternates doesn't
exist.
patch 1,2 are modernizing style of t7408,
patches 3,4 are not strictly necessary, but I think it is a good thing
to not leave the submodule related C code in a crippled state (i.e.
allowing only one reference). The shell code would also need this update,
but it looked ugly to me, so I postpone it until more of the submodule code
is written in C.
Thanks,
Stefan
Stefan Beller (6):
t7408: modernize style
t7408: merge short tests, factor out testing method
submodule--helper module-clone: allow multiple references
submodule--helper update-clone: allow multiple references
submodule update: add super-reference flag
clone: reference flag is used for submodules as well
builtin/clone.c | 22 ++++--
builtin/submodule--helper.c | 45 ++++++++----
git-submodule.sh | 12 +++-
t/t7408-submodule-reference.sh | 153 +++++++++++++++++++++++------------------
4 files changed, 147 insertions(+), 85 deletions(-)
--
2.9.2.572.g9d9644e.dirty
From: Stefan Beller <hidden> Date: 2016-08-04 19:52:16
Tests consisting of one line each can be consolidated to have fewer tests
to run as well as fewer lines of code.
When having just a few git commands, do not create a new shell but
use the -C flag in Git to execute in the correct directory.
Signed-off-by: Stefan Beller <redacted>
---
t/t7408-submodule-reference.sh | 50 +++++++++++++++---------------------------
1 file changed, 18 insertions(+), 32 deletions(-)
From: Stefan Beller <hidden> Date: 2016-08-04 19:52:20
Allow the user to pass in multiple references to update_clone.
Currently this is only internal API, but once the shell script is
replaced by a C version, this is needed.
Signed-off-by: Stefan Beller <redacted>
---
builtin/submodule--helper.c | 14 +++++++++-----
git-submodule.sh | 2 +-
2 files changed, 10 insertions(+), 6 deletions(-)
@@ -583,7 +583,7 @@ struct submodule_update_clone {/* configuration parameters which are passed on to the children */intquiet;intrecommend_shallow;-constchar*reference;+structstring_listreferences;constchar*depth;constchar*recursive_prefix;constchar*prefix;
@@ -715,6 +716,15 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,for_each_string_list_item(item,&suc->references)argv_array_pushl(&child->args,"--reference",item->string,NULL);}+if(suc->superreferences.nr){+structstring_list_item*item;+for_each_string_list_item(item,&suc->superreferences){+strbuf_reset(&sb);+argv_array_pushf(&child->args,"--reference=%s/%s",+relative_path(item->string,suc->prefix,&sb),+sub->path);+}+}if(suc->depth)argv_array_push(&child->args,suc->depth);
@@ -835,6 +845,8 @@ static int update_clone(int argc, const char **argv, const char *prefix)N_("rebase, merge, checkout or none")),OPT_STRING_LIST(0,"reference",&suc.references,N_("repo"),N_("reference repository")),+OPT_STRING_LIST(0,"super-reference",&suc.superreferences,N_("repo"),+N_("superproject of a reference repository")),OPT_STRING(0,"depth",&suc.depth,"<depth>",N_("Create a shallow clone truncated to the ""specified number of revisions")),
From: Stefan Beller <hidden> Date: 2016-08-04 19:52:27
No functional change intended. This commit only changes formatting
to the style we recently use, e.g. starting the body of a test with a
single quote on the same line as the header, and then having the test
indented in the following lines.
Whenever we change directories, we do that in subshells.
Signed-off-by: Stefan Beller <redacted>
---
t/t7408-submodule-reference.sh | 138 +++++++++++++++++++++--------------------
1 file changed, 71 insertions(+), 67 deletions(-)
@@ -10,72 +10,76 @@ base_dir=$(pwd)U=$base_dir/UPLOAD_LOG-test_expect_success'preparing first repository'\-'test_create_repoA&&cdA&&-echofirst>file1&&-gitaddfile1&&-gitcommit-mA-initial'--cd"$base_dir"--test_expect_success'preparing second repository'\-'gitcloneAB&&cdB&&-echosecond>file2&&-gitaddfile2&&-gitcommit-mB-addition&&-gitrepack-a-d&&-gitprune'--cd"$base_dir"--test_expect_success'preparing superproject'\-'test_create_reposuper&&cdsuper&&-echofile>file&&-gitaddfile&&-gitcommit-mB-super-initial'--cd"$base_dir"--test_expect_success'submodule add --reference'\-'cdsuper&&gitsubmoduleadd--reference../B"file://$base_dir/A"sub&&-gitcommit-mB-super-added'--cd"$base_dir"--test_expect_success'after add: existence of info/alternates'\-'test_line_count = 1 super/.git/modules/sub/objects/info/alternates'--cd"$base_dir"--test_expect_success'that reference gets used with add'\-'cdsuper/sub&&-echo"0 objects, 0 kilobytes">expected&&-gitcount-objects>current&&-diffexpectedcurrent'--cd"$base_dir"--test_expect_success'cloning superproject'\-'git clone super super-clone'--cd"$base_dir"--test_expect_success'update with reference'\-'cd super-clone && git submodule update --init --reference ../B'--cd"$base_dir"--test_expect_success'after update: existence of info/alternates'\-'test_line_count = 1 super-clone/.git/modules/sub/objects/info/alternates'--cd"$base_dir"--test_expect_success'that reference gets used with update'\-'cdsuper-clone/sub&&-echo"0 objects, 0 kilobytes">expected&&-gitcount-objects>current&&-diffexpectedcurrent'--cd"$base_dir"+test_expect_success'preparing first repository''+test_create_repoA&&+(+cdA&&+echofirst>file1&&+gitaddfile1&&+gitcommit-mA-initial+)+'++test_expect_success'preparing second repository''+gitcloneAB&&+(+cdB&&+echosecond>file2&&+gitaddfile2&&+gitcommit-mB-addition&&+gitrepack-a-d&&+gitprune+)+'++test_expect_success'preparing superproject''+test_create_reposuper&&+(+cdsuper&&+echofile>file&&+gitaddfile&&+gitcommit-mB-super-initial+)+'++test_expect_success'submodule add --reference''+(+cdsuper&&+gitsubmoduleadd--reference../B"file://$base_dir/A"sub&&+gitcommit-mB-super-added+)+'++test_expect_success'after add: existence of info/alternates''+test_line_count=1super/.git/modules/sub/objects/info/alternates+'++test_expect_success'that reference gets used with add''+(+cdsuper/sub&&+echo"0 objects, 0 kilobytes">expected&&+gitcount-objects>current&&+diffexpectedcurrent+)+'++test_expect_success'cloning superproject''+gitclonesupersuper-clone+'++test_expect_success'update with reference''+cdsuper-clone&&gitsubmoduleupdate--init--reference../B+'++test_expect_success'after update: existence of info/alternates''+test_line_count=1super-clone/.git/modules/sub/objects/info/alternates+'++test_expect_success'that reference gets used with update''+cdsuper-clone/sub&&+echo"0 objects, 0 kilobytes">expected&&+gitcount-objects>current&&+diffexpectedcurrent+' test_done
From: Stefan Beller <hidden> Date: 2016-08-04 19:52:33
When giving a --reference while also giving --recurse, the alternates
for the submodules are assumed to be in the superproject as well.
In case they are not, we error out when cloning the submodule.
However the update command succeeds as usual (with no alternates).
Signed-off-by: Stefan Beller <redacted>
---
builtin/clone.c | 22 ++++++++++++++++++----
t/t7408-submodule-reference.sh | 31 ++++++++++++++++++++++++++++++-
2 files changed, 48 insertions(+), 5 deletions(-)
@@ -68,4 +69,32 @@ test_expect_success 'updating superproject keeps alternates' 'test_alternate_usagesuper-clone/.git/modules/sub/objects/info/alternatessuper-clone/sub'+test_expect_success'submodules use alternates when cloning a superproject''+test_when_finished"rm -rf super-clone"&&+gitclone--referencesuper--recursivesupersuper-clone&&+(+cdsuper-clone&&+# test superproject has alternates setup correctly+test_alternate_usage.git/objects/info/alternates.&&+# test submodule has correct setup+test_alternate_usage.git/modules/sub/objects/info/alternatessub+)+'++test_expect_success'cloning superproject, missing submodule alternates''+test_when_finished"rm -rf super-clone"&&+gitclonesupersuper2&&+test_must_failgitclone--recursive--referencesuper2super2super-clone&&+(+cdsuper-clone&&+# test superproject has alternates setup correctly+test_alternate_usage.git/objects/info/alternates.&&+# update of the submodule succeeds+gitsubmoduleupdate--init&&+# and we have no alternates:+test_must_failtest_alternate_usage.git/modules/sub/objects/info/alternatessub&&+test_path_is_filesub/file1+)+'+ test_done
Note how this changed the API of the submodule--helper.
Currently we pass in --reference $reference
and $reference consists of the string "--reference" and the actual
reference. So it looked like '--reference' '--reference=foo'
That is why we can pass the argument unseen to clone in the helper
via
argv_array_push(&child->args, suc->reference);
This is fixed now.
From: Stefan Beller <hidden> Date: 2016-08-06 21:10:19
When moving code around, we usually get large chunks of text. If the contributor
is not 100% trustworthy, we need to review all the code without much intelectual
joy. Essentially the reviewer is just making sure the parts of the text are the
same.
I'd like to propose a new addition to the diff format that makes this use case
easier. The idea is to mark up lines that were just moved around in the file
instead of adding and removing them.
Currently we have 3 characters that
are allowed to start a line within a hunk:
' ' to indicate context
'+' to add a line
'-' to remove a line
I'd propose to add the following characters:
'*' which is the same as '+', but it indicates that the line was moved
from somewhere else without change.
'X' The same as '-', with the addition that this line was moved to a different
place without change.
The patch below uses these new '*' and 'X'. Each hunk that makes use of these
additions, is followed other sections, [moved-from, moved-to] that indicate
where the corresponding line is.
There are multiple things to tackle when going for such an addition:
* How to present this to the user (it's covered in this email)
* how to find the renamed lines algorithmically.
(there are already approaches to that, e.g. https://github.com/stefanbeller/duplo
which is http://duplo.sourceforge.net/ with no substantial additions)
Any comments welcome,
Thanks,
Stefan
---
t/t7408-submodule-reference.sh | 50 +++++++++++++++---------------------------
1 file changed, 15 insertions(+), 29 deletions(-), 6 moved lines
* echo "0 objects, 0 kilobytes" >expect &&
* git -C $working_dir count-objects >current &&
* diff expect current
+}
+
test_expect_success 'preparing first repository' '
test_create_repo A &&
(
@@ move-source 42,6 @@ test_expect_success 'that reference gets used with add' ' test_expect_success 'that reference gets used with add' ' ( cd super/sub &&
X echo "0 objects, 0 kilobytes" > expected &&
X git count-objects > current &&
X diff expected current
)
'
@@ -42,44 +52,20 @@ test_expect_success 'preparing superproject' ' ) '-test_expect_success 'submodule add --reference' '+test_expect_success 'submodule add --reference uses alternates' ' ( cd super && git submodule add --reference ../B "file://$base_dir/A" sub && git commit -m B-super-added- )-'--test_expect_success 'after add: existence of info/alternates' '- test_line_count = 1 super/.git/modules/sub/objects/info/alternates-'--test_expect_success 'that reference gets used with add' '- (- cd super/sub &&
X echo "0 objects, 0 kilobytes" > expected &&
X git count-objects > current &&
X diff expected current
- )
-'
-
-test_expect_success 'cloning superproject' '
- git clone super super-clone
-'
-
From: René Scharfe <hidden> Date: 2016-08-07 09:24:57
Am 06.08.2016 um 01:26 schrieb Stefan Beller:
When moving code around, we usually get large chunks of text. If the contributor
is not 100% trustworthy, we need to review all the code without much intelectual
joy. Essentially the reviewer is just making sure the parts of the text are the
same.
I'd like to propose a new addition to the diff format that makes this use case
easier. The idea is to mark up lines that were just moved around in the file
instead of adding and removing them.
Currently we have 3 characters that
are allowed to start a line within a hunk:
' ' to indicate context
'+' to add a line
'-' to remove a line
I'd propose to add the following characters:
'*' which is the same as '+', but it indicates that the line was moved
from somewhere else without change.
'X' The same as '-', with the addition that this line was moved to a different
place without change.
The patch below uses these new '*' and 'X'. Each hunk that makes use of these
additions, is followed other sections, [moved-from, moved-to] that indicate
where the corresponding line is.
Interesting idea. It should be easy to convert the result into a regular
unified diff for consumption with patch(1) or git am/apply by replacing
the new flags with + and - and removing the moved-* hunks.
Your example ignores whitespace changes at the start of the line and
within it, the added "-C $working_dir", s/expected/expect/; is this all
intended? Only a single blank line was moved verbatim.
The moved-from and moved-to hunks make this diff quite verbose.
If multiple lines from different sources are moved to the same hunk then
you'd get multiple moved-from hunks following that single destination,
right? (Same with lines moved from a single hunk to multiple
destinations and moved-to.)
But does it even warrent a new format? It's a display problem; the
necessary information is already in the diffs we have today. A
graphical diff viewer could connect moved blocks with lines, like
http://www.araxis.com/merge/ does in its side-by-side view. A
Thunderbird extension (or a bookmarklet or browser extendiion for
webmail users) could do that for an email-based workflow.
Still, what about adding information about moved lines as an extended
header (like that index line)? Line numbers are included in hunk
headers and can serve as orientation. A reader would have to do some
mental arithmetic (ugh), but incompatible format changes would be
avoided. For your example it should look something like this:
move from t/t7408-submodule-reference.sh:52,1
move to t/t7408-submodule-reference.sh:22,1
quoted hunk
There are multiple things to tackle when going for such an addition:
* How to present this to the user (it's covered in this email)
* how to find the renamed lines algorithmically.
(there are already approaches to that, e.g. https://github.com/stefanbeller/duplo
which is http://duplo.sourceforge.net/ with no substantial additions)
Any comments welcome,
Thanks,
Stefan
---
t/t7408-submodule-reference.sh | 50 +++++++++++++++---------------------------
1 file changed, 15 insertions(+), 29 deletions(-), 6 moved lines
test_expect_success 'preparing first repository' '
test_create_repo A &&
(
@@ move-source 42,6 @@ test_expect_success 'that reference gets used with add' ' test_expect_success 'that reference gets used with add' ' ( cd super/sub &&
X echo "0 objects, 0 kilobytes" > expected &&
X git count-objects > current &&
X diff expected current
)
'