Several git programs take long dash-less options on the command-line
to indicate different modes of operation like:
git stash show
git bundle verify test.bundle
git bisect start
Currently, the parse-options framework forbids the use of
opts->long_name and OPT_PARSE_NODASH, and the parsing has to be done
by hand as a result. Lift this restriction, and create a new
OPT_SUBCOMMAND; this is built on top of OPTION_BIT to allow for the
detection of more than one subcommand.
Signed-off-by: Ramkumar Ramachandra <redacted>
---
parse-options.c | 5 +++--
parse-options.h | 3 +++
t/t0040-parse-options.sh | 31 +++++++++++++++++++++++++++++++
test-parse-options.c | 4 ++++
4 files changed, 41 insertions(+), 2 deletions(-)
@@ -40,6 +41,8 @@ int main(int argc, const char **argv)OPT_BOOLEAN('b',"boolean",&boolean,"get a boolean"),OPT_BIT('4',"or4",&boolean,"bitwise-or boolean with ...0100",4),+OPT_SUBCOMMAND("sub4",&subcommand,+"bitwise-or subcommand with ...0100",4),OPT_NEGBIT(0,"neg-or4",&boolean,"same as --no-or4",4),OPT_GROUP(""),OPT_INTEGER('i',"integer",&integer,"get a integer"),
The git-bundle builtin currently parses command-line options by hand;
this is both fragile and cryptic on failure. Since we now have an
OPT_SUBCOMMAND, make use of it to parse the correct subcommand, while
forbidding the use of more than one subcommand in the same invocation.
Signed-off-by: Ramkumar Ramachandra <redacted>
---
builtin/bundle.c | 111 +++++++++++++++++++++++++++++++++++------------------
1 files changed, 73 insertions(+), 38 deletions(-)
@@ -9,57 +10,91 @@*bundlesupporting"fetch","pull",and"ls-remote".*/-staticconstcharbuiltin_bundle_usage[]=-"git bundle create <file> <git-rev-list args>\n"-" or: git bundle verify <file>\n"-" or: git bundle list-heads <file> [<refname>...]\n"-" or: git bundle unbundle <file> [<refname>...]";+staticconstchar*builtin_bundle_usage[]={+"git bundle create <file> <git-rev-list args>",+"git bundle verify <file>",+"git bundle list-heads <file> [<refname>...]",+"git bundle unbundle <file> [<refname>...]",+NULL+};++enumbundle_subcommand{+BUNDLE_NONE=0,+BUNDLE_CREATE=1,+BUNDLE_VERIFY=2,+BUNDLE_LIST_HEADS=4,+BUNDLE_UNBUNDLE=8+};intcmd_bundle(intargc,constchar**argv,constchar*prefix){-structbundle_headerheader;-constchar*cmd,*bundle_file;+intprefix_length;intbundle_fd=-1;-charbuffer[PATH_MAX];+constchar*bundle_file;+structbundle_headerheader;+enumbundle_subcommandsubcommand=BUNDLE_NONE;-if(argc<3)-usage(builtin_bundle_usage);+structoptionoptions[]={+OPT_SUBCOMMAND("create",&subcommand,+"create a new bundle",+BUNDLE_CREATE),+OPT_SUBCOMMAND("verify",&subcommand,+"verify clean application of the bundle",+BUNDLE_VERIFY),+OPT_SUBCOMMAND("list-heads",&subcommand,+"list references defined in the bundle",+BUNDLE_LIST_HEADS),+OPT_SUBCOMMAND("unbundle",&subcommand,+"pass objects in the bundle to 'git index-pack'",+BUNDLE_UNBUNDLE),+OPT_END(),+};-cmd=argv[1];-bundle_file=argv[2];-argc-=2;-argv+=2;+argc=parse_options(argc,argv,NULL,+options,builtin_bundle_usage,+PARSE_OPT_KEEP_ARGV0|PARSE_OPT_KEEP_UNKNOWN);-if(prefix&&bundle_file[0]!='/'){-snprintf(buffer,sizeof(buffer),"%s/%s",prefix,bundle_file);-bundle_file=buffer;-}+if(argc<2)+usage_with_options(builtin_bundle_usage,options);-memset(&header,0,sizeof(header));-if(strcmp(cmd,"create")&&(bundle_fd=-read_bundle_header(bundle_file,&header))<0)-return1;+/* The next parameter on the command line is bundle_file */+prefix_length=prefix?strlen(prefix):0;+bundle_file=prefix_filename(prefix,prefix_length,argv[1]);+argc-=1;+argv+=1;-if(!strcmp(cmd,"verify")){+/* Read out bundle header, except in BUNDLE_CREATE case */+if(subcommand==BUNDLE_VERIFY||subcommand==BUNDLE_LIST_HEADS||+subcommand==BUNDLE_UNBUNDLE){+memset(&header,0,sizeof(header));+bundle_fd=read_bundle_header(bundle_file,&header);+if(bundle_fd<0)+die_errno(_("Failed to open bundle file '%s'"),bundle_file);+}++switch(subcommand){+caseBUNDLE_CREATE:+if(!startup_info->have_repository)+die(_("Need a repository to create a bundle."));+returncreate_bundle(&header,bundle_file,argc,argv);+caseBUNDLE_VERIFY:close(bundle_fd);if(verify_bundle(&header,1))-return1;+return-1;/* Error already reported */fprintf(stderr,_("%s is okay\n"),bundle_file);-return0;-}-if(!strcmp(cmd,"list-heads")){+break;+caseBUNDLE_LIST_HEADS:close(bundle_fd);-return!!list_bundle_refs(&header,argc,argv);-}-if(!strcmp(cmd,"create")){-if(!startup_info->have_repository)-die(_("Need a repository to create a bundle."));-return!!create_bundle(&header,bundle_file,argc,argv);-}elseif(!strcmp(cmd,"unbundle")){-if(!startup_info->have_repository)+returnlist_bundle_refs(&header,argc,argv);+caseBUNDLE_UNBUNDLE:+if(!startup_info->have_repository){+close(bundle_fd);die(_("Need a repository to unbundle."));-return!!unbundle(&header,bundle_fd,0)||+}+returnunbundle(&header,bundle_fd,0)||list_bundle_refs(&header,argc,argv);-}else-usage(builtin_bundle_usage);+default:+usage_with_options(builtin_bundle_usage,options);+}+return0;}
Put the opening quote starting each test on the same line as the
test_expect_* invocation. While at it:
- Indent the file with tabs, not spaces.
- Guard commands that prepare test input for individual tests in the
same test_expect_success, so that their scope is clearer and errors
at that stage can be caught.
- Use <<-\EOF in preference to <<EOF to save readers the trouble of
looking for variable interpolations.
- Include "setup" in the titles of test assertions that prepare for
later ones to make it more obvious which tests can be skipped.
- Chain commands with &&. Breaks in a test assertion's && chain can
potentially hide failures from earlier commands in the chain.
- Use test_expect_code() in preference to checking the exit status of
various statements by hand.
Helped-by: Jonathan Nieder [off-list ref]
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t3040-subprojects-basic.sh | 144 +++++++++++++++++++++---------------------
1 files changed, 72 insertions(+), 72 deletions(-)
@@ -3,81 +3,81 @@test_description='Basic subproject functionality' ../test-lib.sh-test_expect_success'Super project creation'\-':>Makefile&&-gitaddMakefile&&-gitcommit-m"Superproject created"'---cat>expected<<EOF-:00000016000000000...Asub1-:00000016000000000...Asub2-EOF-test_expect_success'create subprojects'\-'mkdirsub1&&-(cdsub1&&gitinit&&:>Makefile&&gitadd*&&-gitcommit-q-m"subproject 1")&&-mkdirsub2&&-(cdsub2&&gitinit&&:>Makefile&&gitadd*&&-gitcommit-q-m"subproject 2")&&-gitupdate-index--addsub1&&-gitaddsub2&&-gitcommit-q-m"subprojects added"&&-gitdiff-tree--abbrev=5HEAD^HEAD|cut-d" "-f-3,5->current&&-test_cmpexpectedcurrent'--gitbranchsaveHEAD--test_expect_success'check if fsck ignores the subprojects'\-'git fsck --full'--test_expect_success'check if commit in a subproject detected'\-'(cdsub1&&-echo"all:">>Makefile&&-echo" true">>Makefile&&-gitcommit-q-a-m"make all")&&{-gitdiff-files--exit-code-test$?=1-}'--test_expect_success'check if a changed subproject HEAD can be committed'\-'gitcommit-q-a-m"sub1 changed"&&{-gitdiff-tree--exit-codeHEAD^HEAD-test$?=1-}'--test_expect_success'check if diff-index works for subproject elements'\-'gitdiff-index--exit-code--cachedsave--sub1-test$?=1'--test_expect_success'check if diff-tree works for subproject elements'\-'gitdiff-tree--exit-codeHEAD^HEAD--sub1-test$?=1'--test_expect_success'check if git diff works for subproject elements'\-'gitdiff--exit-codeHEAD^HEAD-test$?=1'--test_expect_success'check if clone works'\-'gitls-files-s>expected&&-gitclone-l-s.cloned&&-(cdcloned&&gitls-files-s)>current&&-test_cmpexpectedcurrent'--test_expect_success'removing and adding subproject'\-'gitupdate-index--force-remove--sub2&&-mvsub2sub3&&-gitaddsub3&&-gitcommit-q-m"renaming a subproject"&&{-gitdiff-M--name-status--exit-codeHEAD^HEAD-test$?=1-}'+test_expect_success'setup: create superproject''+:>Makefile&&+gitaddMakefile&&+gitcommit-m"Superproject created"+'++test_expect_success'setup: create subprojects''+mkdirsub1&&+(cdsub1&&gitinit&&:>Makefile&&gitadd*&&+gitcommit-q-m"subproject 1")&&+mkdirsub2&&+(cdsub2&&gitinit&&:>Makefile&&gitadd*&&+gitcommit-q-m"subproject 2")&&+gitupdate-index--addsub1&&+gitaddsub2&&+gitcommit-q-m"subprojects added"&&+gitdiff-tree--abbrev=5HEAD^HEAD|cut-d" "-f-3,5->current&&+gitbranchsaveHEAD&&+cat>expected<<-\EOF&&+:00000016000000000...Asub1+:00000016000000000...Asub2+EOF+test_cmpexpectedcurrent+'++test_expect_success'check if fsck ignores the subprojects''+gitfsck--full+'++test_expect_success'check if commit in a subproject detected''+(cdsub1&&+echo"all:">>Makefile&&+echo" true">>Makefile&&+gitcommit-q-a-m"make all")&&+test_expect_code1gitdiff-files--exit-code+'++test_expect_success'check if a changed subproject HEAD can be committed''+gitcommit-q-a-m"sub1 changed"&&+test_expect_code1gitdiff-tree--exit-codeHEAD^HEAD+'++test_expect_success'check if diff-index works for subproject elements''+test_expect_code1gitdiff-index--exit-code--cachedsave--sub1+'++test_expect_success'check if diff-tree works for subproject elements''+test_expect_code1gitdiff-tree--exit-codeHEAD^HEAD--sub1+'++test_expect_success'check if git diff works for subproject elements''+test_expect_code1gitdiff--exit-codeHEAD^HEAD+'++test_expect_success'check if clone works''+gitls-files-s>expected&&+gitclone-l-s.cloned&&+(cdcloned&&gitls-files-s)>current&&+test_cmpexpectedcurrent+'++test_expect_success'removing and adding subproject''+gitupdate-index--force-remove--sub2&&+mvsub2sub3&&+gitaddsub3&&+gitcommit-q-m"renaming a subproject"&&+test_expect_code1gitdiff-M--name-status--exit-codeHEAD^HEAD+'# the index must contain the object name the HEAD of the# subproject sub1 was at the point "save"-test_expect_success'checkout in superproject'\-'gitcheckoutsave&&-gitdiff-index--exit-code--raw--cachedsave--sub1'+test_expect_success'checkout in superproject''+gitcheckoutsave&&+gitdiff-index--exit-code--raw--cachedsave--sub1+'# just interesting what happened...# git diff --name-status -M save master
@@ -422,17 +392,7 @@ test_expect_success 'merge-recursive d/f conflict the other way' 'gitreset--hard&&gitcheckout-f"$c4"&&-gitmerge-recursive"$c0"--"$c4""$c1"-status=$?-case"$status"in-1)-:happy-;;-*)-echo>&2"why status $status!!!"-false-;;-esac+test_expect_code1gitmerge-recursive"$c0"--"$c4""$c1"' test_expect_success'merge-recursive d/f conflict result the other way''
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
Additionally, note that 'git branch --help' will fail when git
manpages aren't already installed: guard the line with a
'test_might_fail'.
Helped-by: Jonathan Nieder [off-list ref]
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t3200-branch.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
@@ -22,7 +22,7 @@ test_expect_success \ test_expect_success\'git branch --help should not have created a bogus branch''-gitbranch--help</dev/null>/dev/null2>/dev/null;+test_might_failgitbranch--help</dev/null>/dev/null2>/dev/null&&test_path_is_missing.git/refs/heads/--help'
@@ -88,7 +88,7 @@ test_expect_success \ test_expect_success\'git branch -m n/n n should work'\'gitbranch-ln/n&&-gitbranch-mn/nn+gitbranch-mn/nn&&test_path_is_file.git/logs/refs/heads/n' test_expect_success'git branch -m o/o o should fail when o/p exists''
@@ -36,66 +36,41 @@ $content"'test_expect_success"Type of $type is correct"'-test$type="$(gitcat-file-t$sha1)"+echo$type>expect&&+gitcat-file-t$sha1>actual&&+test_cmpexpectactual'test_expect_success"Size of $type is correct"'-test$size="$(gitcat-file-s$sha1)"+echo$size>expect&&+gitcat-file-s$sha1>actual&&+test_cmpexpectactual'test-z"$content"||test_expect_success"Content of $type is correct"'-expect="$(maybe_remove_timestamp"$content"$no_ts)"-actual="$(maybe_remove_timestamp"$(gitcat-file$type$sha1)"$no_ts)"--iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+maybe_remove_timestamp"$content"$no_ts>expect&&+maybe_remove_timestamp"$(gitcat-file$type$sha1)"$no_ts>actual&&+test_cmpexpectactual'test_expect_success"Pretty content of $type is correct"'-expect="$(maybe_remove_timestamp"$pretty_content"$no_ts)"-actual="$(maybe_remove_timestamp"$(gitcat-file-p$sha1)"$no_ts)"-iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+maybe_remove_timestamp"$pretty_content"$no_ts>expect&&+maybe_remove_timestamp"$(gitcat-file-p$sha1)"$no_ts>actual&&+test_cmpexpectactual'test-z"$content"||test_expect_success"--batch output of $type is correct"'-expect="$(maybe_remove_timestamp"$batch_output"$no_ts)"-actual="$(maybe_remove_timestamp"$(echo$sha1|gitcat-file--batch)"$no_ts)"-iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+maybe_remove_timestamp"$batch_output"$no_ts>expect&&+maybe_remove_timestamp"$(echo$sha1|gitcat-file--batch)"$no_ts>actual&&+test_cmpexpectactual'test_expect_success"--batch-check output of $type is correct"'-expect="$sha1$type$size"-actual="$(echo_without_newline$sha1|gitcat-file--batch-check)"-iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+echo"$sha1$type$size">expect&&+echo_without_newline$sha1|gitcat-file--batch-check>actual&&+test_cmpexpectactual'}
@@ -144,10 +119,13 @@ tag_size=$(strlen "$tag_content") run_tests'tag'$tag_sha1$tag_size"$tag_content""$tag_pretty_content"1-test_expect_success\-"Reach a blob from a tag pointing to it"\-"test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""+test_expect_success"Reach a blob from a tag pointing to it"'+echo_without_newline"$hello_content">expect&&+gitcat-fileblob"$tag_sha1">actual&&+test_cmpexpectactual+'+test_doneforbatchinbatchbatch-checkdoforoptintsep
@@ -175,30 +153,41 @@ dodone test_expect_success"--batch-check for a non-existent named object"'-test"foobar42 missing-foobar84missing" = \-"$((echofoobar42;echo_without_newlinefoobar84;) | git cat-file --batch-check)"+cat>expect<<\-EOF&&+foobar42missing+foobar84missing+EOF+$(echofoobar42;echo_without_newlinefoobar84)\+|gitcat-file--batch-check>actual&&+test_cmpexpectactual' test_expect_success"--batch-check for a non-existent hash"'-test"0000000000000000000000000000000000000042 missing-0000000000000000000000000000000000000084missing" = \-"$((echo0000000000000000000000000000000000000042;-echo_without_newline0000000000000000000000000000000000000084;)\-|gitcat-file--batch-check)"+cat>expect<<\-EOF&&+0000000000000000000000000000000000000042missing+0000000000000000000000000000000000000084missing+EOF+$(echo0000000000000000000000000000000000000042;+echo_without_newline0000000000000000000000000000000000000084)\+|gitcat-file--batch-check>actual&&+test_cmpexpectactual' test_expect_success"--batch for an existent and a non-existent hash"'-test"$tag_sha1 tag $tag_size+cat>expect<<\-EOF&&+tag_sha1tag$tag_size$tag_content-0000000000000000000000000000000000000000missing" = \-"$((echo$tag_sha1;-echo_without_newline0000000000000000000000000000000000000000;)\-|gitcat-file--batch)"+0000000000000000000000000000000000000000missing+EOF+$(echo$tag_sha1;echo_without_newline0000000000000000000000000000000000000000)\+|gitcat-file--batch>actual&&+test_cmpexpect_actual' test_expect_success"--batch-check for an emtpy line"'-test" missing"="$(echo|gitcat-file--batch-check)"+echo" missing">expect&&+echo|gitcat-file--batch-check>actual&&+test_cmpexpectactual'batch_input="$hello_sha1
@@ -389,7 +389,7 @@ test_expect_success 'abort notes merge' 'test_must_faills.git/NOTES_MERGE_*>output2>/dev/null&&test_cmp/dev/nulloutput&&# m has not moved (still == y)-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -525,9 +525,9 @@ EOFtest-f.git/NOTES_MERGE_WORKTREE/$commit_sha3&&test-f.git/NOTES_MERGE_WORKTREE/$commit_sha4&&# Refs are unchanged-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"-test"$(gitrev-parserefs/notes/y)"="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"-test"$(gitrev-parserefs/notes/m)"!="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"+test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&+test"$(gitrev-parserefs/notes/y)"="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&+test"$(gitrev-parserefs/notes/m)"!="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&# Mention refs/notes/m, and its current and expected value in outputgrep-q"refs/notes/m"output&&grep-q"$(gitrev-parserefs/notes/m)"output&&
@@ -545,7 +545,7 @@ test_expect_success 'resolve situation by aborting the notes merge' 'test_must_faills.git/NOTES_MERGE_*>output2>/dev/null&&test_cmp/dev/nulloutput&&# m has not moved (still == w)-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"+test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -172,8 +172,8 @@ test_expect_success 'fail when upstream arg is missing and not configured' ' test_expect_success'default to @{upstream} when upstream arg is missing''gitcheckout-bdefaulttopic&&-gitconfigbranch.default.remote.-gitconfigbranch.default.mergerefs/heads/master+gitconfigbranch.default.remote.&&+gitconfigbranch.default.mergerefs/heads/master&&gitrebase&&test"$(gitrev-parsedefault~1)"="$(gitrev-parsemaster)"'
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
Additionally, note that 'unset' returns non-zero status when the
variable passed was already unset on some shells: change these
instances to 'safe_unset'.
Helped-by: Jonathan Nieder [off-list ref]
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t1501-worktree.sh | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Hi,
Quick thoughts:
Ramkumar Ramachandra wrote:
Currently, the parse-options framework forbids the use of
opts->long_name and OPT_PARSE_NODASH, and the parsing has to be done
by hand as a result. Lift this restriction
This part seems like a sane idea to me.
, and create a new
OPT_SUBCOMMAND; this is built on top of OPTION_BIT to allow for the
detection of more than one subcommand.
This part I am not convinced about. Usually each subcommand takes its
own options, so I cannot see this OPT_SUBCOMMAND being actually useful
for commands like "git stash" or "git remote".
Hope that helps,
Jonathan
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Put the opening quote starting each test on the same line as the
test_expect_* invocation. While at it:
I suspect the above description, while it does describe your patch,
does not describe the _reason_ that the patch exists or that someone
would want to apply it. Isn't it something more like:
Make the following changes pertaining to &&-chaining, for some
good reason that I will describe:
- ...
While at it, clean up the style to fit the prevailing style.
That means:
- Put the opening quote starting each test on the same line as
...
I didn't read over the patch again. Has it changed since v1?
Doesn't this make the usage completely confusing? Before, if I wanted
to create bundle named "verify", I could write
git bundle create verify
Afterwards, not only does that not work, but if I make a typo and
write
git bundle ceate verify
then it will act like "git bundle verify ceate".
I am starting to suspect the first half of patch 1/2 was not such a
great idea, either. :) Do you have other examples of how it would be
used?
Thanks for thining about these things, and hope that helps.
Jonathan
, and create a new
OPT_SUBCOMMAND; this is built on top of OPTION_BIT to allow for the
detection of more than one subcommand.
This part I am not convinced about. Usually each subcommand takes its
own options, so I cannot see this OPT_SUBCOMMAND being actually useful
for commands like "git stash" or "git remote".
Hm, what difference does that make? We still have to parse the
subcommand, and subsequently use an if-else construct to parse more
options depending on the subcommand, no?
-- Ram
Doesn't this make the usage completely confusing? Before, if I wanted
to create bundle named "verify", I could write
git bundle create verify
Afterwards, not only does that not work, but if I make a typo and
write
git bundle ceate verify
then it will act like "git bundle verify ceate".
No it won't -- it'll just print out the usage because "verify" and
"create" are mutually exclusive options. Sure, you can't create a
bundle named "verify", but that's the compromise you'll have to make
if you don't want to type out "--" with each option, no?
I am starting to suspect the first half of patch 1/2 was not such a
great idea, either. :) Do you have other examples of how it would be
used?
Hehe, my lack of foresight is disturbing as usual. I'm not yet sure
it'll be useful.
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Use test_cmp in preference to repeatedly comparing command outputs by
hand.
That could mean one of several things.
It could mean:
1. Use test_cmp instead of open-coding it.
2. Use test_cmp instead of using our knowledge of the underlying
filesystem to retrieve the files from the block device, instead
of relying on the perfectly good operating system facilities
that could take care of it for us
3. Use test_cmp instead of calling a human over to compare command
outputs by eye, which idiomatically might be described as "by
hand".
What I mean is, I actually don't have much of a clue what you mean by
"by hand". Usually it means "not automated sufficiently", but I think
that is not the entire problem here (since
test "$expect" = "$actual"
looks no less automatic than
printf '%s\n' "$expect" >expect &&
printf '%s\n' "$actual" >actual &&
test_cmp expect actual
to me).
Most of the early part of patch proper looks sane from a quick glance.
Wow, the whitespace is a little strange in the original.
[...]
quoted hunk
@@ -175,30 +153,41 @@ do done test_expect_success "--batch-check for a non-existent named object" '- test "foobar42 missing-foobar84 missing" = \- "$( ( echo foobar42; echo_without_newline foobar84; ) | git cat-file --batch-check)"+ cat >expect <<\-EOF &&+foobar42 missing+foobar84 missing+EOF+ $(echo foobar42; echo_without_newline foobar84) \+ | git cat-file --batch-check >actual &&+ test_cmp expect actual
Style: the | character goes at the end of the first line (think of it
as a way to save backslashes until they're needed).
How could this $(...) command substitution possibly work?
Later tests have the same problem, so I'm stopping here.
Ciao,
Jonathan
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Sure, you can't create a
bundle named "verify", but that's the compromise you'll have to make
if you don't want to type out "--" with each option, no?
No, that's not a compromise I'll have to make. I'm not making it today.
Having to type "--" or prefix with "./" to escape ordinary filenames
that do not start with "-" would be completely weird. This is
important to me: I want you to see it, rather than relying on me as an
authority figure to say it (after all, I'm not such a great authority
anyway --- I make plenty of mistakes).
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
Additionally, note that 'git branch --help' will fail when git
This is not "Additionally, while we're here" but rather "In order to
do so".
manpages aren't already installed: guard the line with a
'test_might_fail'.
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t3200-branch.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
For what it's worth,
Acked-by: Jonathan Nieder <redacted>
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
Additionally, note that 'unset' returns non-zero status when the
variable passed was already unset on some shells: change these
instances to 'safe_unset'.
This is also not "Additionally", as in "As a separate change that
maybe should have been another patch but I am too lazy". Rather, it
is a necessary change that is part of the same task. So I would
write:
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
'unset' returns non-zero status when the variable passed was already
unset on some shells, so now that the status is tested we need to
change these instances to 'safe_unset'.
Erm, sane_unset, not safe_unset. Did you even test this?
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix instances of this in the
following tests:
t3419 (rebase-patch-id)
t3310 (notes-merge-manual-resolve)
[...]
The reader can read the diffstat, so I am not sure this list is very
useful.
With the space gained, it might be helpful to mention that this patch
only adds " &&" to the ends of lines and that any other kind of change
here would be unintentional, to put the reader's mind at ease.
[...]
Signed-off-by: Ramkumar Ramachandra <redacted>
The patch proper looks good, so if this is tested,
Acked-by: Jonathan Nieder <redacted>
Sure, you can't create a
bundle named "verify", but that's the compromise you'll have to make
if you don't want to type out "--" with each option, no?
Having to type "--" or prefix with "./" to escape ordinary filenames
that do not start with "-" would be completely weird.
Hm, do you have any suggestions to work around this? Can we use
something like a parse-stopper after the the first subcommand is
encountered, and treat the next argument as a non-subcommand (filename
or whatever else)?
-- Ram
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:35
Ramkumar Ramachandra wrote:
Jonathan Nieder wrote:
quoted
Having to type "--" or prefix with "./" to escape ordinary filenames
that do not start with "-" would be completely weird.
Hm, do you have any suggestions to work around this? Can we use
something like a parse-stopper after the the first subcommand is
encountered, and treat the next argument as a non-subcommand (filename
or whatever else)?
What's the desired behavior? Then we can talk about how to implement it.
If the goal is "use parse-options for a command that has subcommands",
see builtin/notes.c.
What's the desired behavior? Then we can talk about how to implement it.
If the goal is "use parse-options for a command that has subcommands",
see builtin/notes.c.
Uses strcmp() to match argv[0]. And you can't specify the options for
a certain subcommand before the subcommand itself on the command-line,
although I don't consider this a serious limitation. I was going for
something prettier with subcommand-specific help text, albeit a
serious limitation. I'll try working towards this for a few more
hours to see if anything useful comes out of it -- otherwise, I'll
just drop this patch and focus on eliminating the ugliness in
builtin/revert.c around '--continue', '--quit' parsing.
That being said, do you see value in lifting the restriction on
opts->long_name and PARSE_OPTS_NODASH not allowed together? The
restriction seems quite arbitrary, but I can't justify lifting it
unless I can show some valid usecase.
Thanks.
-- Ram
Put the opening quote starting each test on the same line as the
test_expect_* invocation. While at it:
I suspect the above description, while it does describe your patch,
does not describe the _reason_ that the patch exists or that someone
would want to apply it. Isn't it something more like:
[...]
Right, fixed.
I didn't read over the patch again. Has it changed since v1?
No. I refrained from making other style changes and/ or combining tests.
-- Ram
@@ -422,17 +392,7 @@ test_expect_success 'merge-recursive d/f conflict the other way' 'gitreset--hard&&gitcheckout-f"$c4"&&-gitmerge-recursive"$c0"--"$c4""$c1"-status=$?-case"$status"in-1)-:happy-;;-*)-echo>&2"why status $status!!!"-false-;;-esac+test_expect_code1gitmerge-recursive"$c0"--"$c4""$c1"' test_expect_success'merge-recursive d/f conflict result the other way''
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix instances of this. While at
it, clean up the style to fit the prevailing style. This means:
- Put the opening quote starting each test on the same line as the
test_expect_* invocation.
- Indent the file with tabs, not spaces.
- Use test_expect_code() in preference to checking the exit status of
various statements by hand.
- Guard commands that prepare test input for individual tests in the
same test_expect_success, so that their scope is clearer and errors
at that stage can be caught.
- Use <<-\EOF in preference to <<EOF to save readers the trouble of
looking for variable interpolations.
- Include "setup" in the titles of test assertions that prepare for
later ones to make it more obvious which tests can be skipped.
Helped-by: Jonathan Nieder [off-list ref]
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t3040-subprojects-basic.sh | 144 +++++++++++++++++++++---------------------
1 files changed, 72 insertions(+), 72 deletions(-)
@@ -3,81 +3,81 @@test_description='Basic subproject functionality' ../test-lib.sh-test_expect_success'Super project creation'\-':>Makefile&&-gitaddMakefile&&-gitcommit-m"Superproject created"'---cat>expected<<EOF-:00000016000000000...Asub1-:00000016000000000...Asub2-EOF-test_expect_success'create subprojects'\-'mkdirsub1&&-(cdsub1&&gitinit&&:>Makefile&&gitadd*&&-gitcommit-q-m"subproject 1")&&-mkdirsub2&&-(cdsub2&&gitinit&&:>Makefile&&gitadd*&&-gitcommit-q-m"subproject 2")&&-gitupdate-index--addsub1&&-gitaddsub2&&-gitcommit-q-m"subprojects added"&&-gitdiff-tree--abbrev=5HEAD^HEAD|cut-d" "-f-3,5->current&&-test_cmpexpectedcurrent'--gitbranchsaveHEAD--test_expect_success'check if fsck ignores the subprojects'\-'git fsck --full'--test_expect_success'check if commit in a subproject detected'\-'(cdsub1&&-echo"all:">>Makefile&&-echo" true">>Makefile&&-gitcommit-q-a-m"make all")&&{-gitdiff-files--exit-code-test$?=1-}'--test_expect_success'check if a changed subproject HEAD can be committed'\-'gitcommit-q-a-m"sub1 changed"&&{-gitdiff-tree--exit-codeHEAD^HEAD-test$?=1-}'--test_expect_success'check if diff-index works for subproject elements'\-'gitdiff-index--exit-code--cachedsave--sub1-test$?=1'--test_expect_success'check if diff-tree works for subproject elements'\-'gitdiff-tree--exit-codeHEAD^HEAD--sub1-test$?=1'--test_expect_success'check if git diff works for subproject elements'\-'gitdiff--exit-codeHEAD^HEAD-test$?=1'--test_expect_success'check if clone works'\-'gitls-files-s>expected&&-gitclone-l-s.cloned&&-(cdcloned&&gitls-files-s)>current&&-test_cmpexpectedcurrent'--test_expect_success'removing and adding subproject'\-'gitupdate-index--force-remove--sub2&&-mvsub2sub3&&-gitaddsub3&&-gitcommit-q-m"renaming a subproject"&&{-gitdiff-M--name-status--exit-codeHEAD^HEAD-test$?=1-}'+test_expect_success'setup: create superproject''+:>Makefile&&+gitaddMakefile&&+gitcommit-m"Superproject created"+'++test_expect_success'setup: create subprojects''+mkdirsub1&&+(cdsub1&&gitinit&&:>Makefile&&gitadd*&&+gitcommit-q-m"subproject 1")&&+mkdirsub2&&+(cdsub2&&gitinit&&:>Makefile&&gitadd*&&+gitcommit-q-m"subproject 2")&&+gitupdate-index--addsub1&&+gitaddsub2&&+gitcommit-q-m"subprojects added"&&+gitdiff-tree--abbrev=5HEAD^HEAD|cut-d" "-f-3,5->current&&+gitbranchsaveHEAD&&+cat>expected<<-\EOF&&+:00000016000000000...Asub1+:00000016000000000...Asub2+EOF+test_cmpexpectedcurrent+'++test_expect_success'check if fsck ignores the subprojects''+gitfsck--full+'++test_expect_success'check if commit in a subproject detected''+(cdsub1&&+echo"all:">>Makefile&&+echo" true">>Makefile&&+gitcommit-q-a-m"make all")&&+test_expect_code1gitdiff-files--exit-code+'++test_expect_success'check if a changed subproject HEAD can be committed''+gitcommit-q-a-m"sub1 changed"&&+test_expect_code1gitdiff-tree--exit-codeHEAD^HEAD+'++test_expect_success'check if diff-index works for subproject elements''+test_expect_code1gitdiff-index--exit-code--cachedsave--sub1+'++test_expect_success'check if diff-tree works for subproject elements''+test_expect_code1gitdiff-tree--exit-codeHEAD^HEAD--sub1+'++test_expect_success'check if git diff works for subproject elements''+test_expect_code1gitdiff--exit-codeHEAD^HEAD+'++test_expect_success'check if clone works''+gitls-files-s>expected&&+gitclone-l-s.cloned&&+(cdcloned&&gitls-files-s)>current&&+test_cmpexpectedcurrent+'++test_expect_success'removing and adding subproject''+gitupdate-index--force-remove--sub2&&+mvsub2sub3&&+gitaddsub3&&+gitcommit-q-m"renaming a subproject"&&+test_expect_code1gitdiff-M--name-status--exit-codeHEAD^HEAD+'# the index must contain the object name the HEAD of the# subproject sub1 was at the point "save"-test_expect_success'checkout in superproject'\-'gitcheckoutsave&&-gitdiff-index--exit-code--raw--cachedsave--sub1'+test_expect_success'checkout in superproject''+gitcheckoutsave&&+gitdiff-index--exit-code--raw--cachedsave--sub1+'# just interesting what happened...# git diff --name-status -M save master
In testing, a common paradigm involves checking the expected output
with the actual output: test-lib provides a test_cmp to show the diff
between the two outputs. So, use this function in preference to
calling a human over to compare command outputs by eye.
Helped-by: Jonathan Nieder [off-list ref]
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t1006-cat-file.sh | 119 ++++++++++++++++++++++++---------------------------
1 files changed, 56 insertions(+), 63 deletions(-)
@@ -36,66 +36,41 @@ $content"'test_expect_success"Type of $type is correct"'-test$type="$(gitcat-file-t$sha1)"+echo$type>expect&&+gitcat-file-t$sha1>actual&&+test_cmpexpectactual'test_expect_success"Size of $type is correct"'-test$size="$(gitcat-file-s$sha1)"+echo$size>expect&&+gitcat-file-s$sha1>actual&&+test_cmpexpectactual'test-z"$content"||test_expect_success"Content of $type is correct"'-expect="$(maybe_remove_timestamp"$content"$no_ts)"-actual="$(maybe_remove_timestamp"$(gitcat-file$type$sha1)"$no_ts)"--iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+maybe_remove_timestamp"$content"$no_ts>expect&&+maybe_remove_timestamp"$(gitcat-file$type$sha1)"$no_ts>actual&&+test_cmpexpectactual'test_expect_success"Pretty content of $type is correct"'-expect="$(maybe_remove_timestamp"$pretty_content"$no_ts)"-actual="$(maybe_remove_timestamp"$(gitcat-file-p$sha1)"$no_ts)"-iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+maybe_remove_timestamp"$pretty_content"$no_ts>expect&&+maybe_remove_timestamp"$(gitcat-file-p$sha1)"$no_ts>actual&&+test_cmpexpectactual'test-z"$content"||test_expect_success"--batch output of $type is correct"'-expect="$(maybe_remove_timestamp"$batch_output"$no_ts)"-actual="$(maybe_remove_timestamp"$(echo$sha1|gitcat-file--batch)"$no_ts)"-iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+maybe_remove_timestamp"$batch_output"$no_ts>expect&&+maybe_remove_timestamp"$(echo$sha1|gitcat-file--batch)"$no_ts>actual&&+test_cmpexpectactual'test_expect_success"--batch-check output of $type is correct"'-expect="$sha1$type$size"-actual="$(echo_without_newline$sha1|gitcat-file--batch-check)"-iftest"z$expect"="z$actual"-then-:happy-else-echo"Oops: expected $expect"-echo"but got $actual"-false-fi+echo"$sha1$type$size">expect&&+echo_without_newline$sha1|gitcat-file--batch-check>actual&&+test_cmpexpectactual'}
@@ -144,10 +119,13 @@ tag_size=$(strlen "$tag_content") run_tests'tag'$tag_sha1$tag_size"$tag_content""$tag_pretty_content"1-test_expect_success\-"Reach a blob from a tag pointing to it"\-"test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""+test_expect_success"Reach a blob from a tag pointing to it"'+echo_without_newline"$hello_content">expect&&+gitcat-fileblob"$tag_sha1">actual&&+test_cmpexpectactual+'+test_doneforbatchinbatchbatch-checkdoforoptintsep
@@ -175,30 +153,41 @@ dodone test_expect_success"--batch-check for a non-existent named object"'-test"foobar42 missing-foobar84missing" = \-"$((echofoobar42;echo_without_newlinefoobar84;) | git cat-file --batch-check)"+cat>expect<<\-EOF&&+foobar42missing+foobar84missing+EOF+echofoobar42;echo_without_newlinefoobar84|\+gitcat-file--batch-check>actual&&+test_cmpexpectactual' test_expect_success"--batch-check for a non-existent hash"'-test"0000000000000000000000000000000000000042 missing-0000000000000000000000000000000000000084missing" = \-"$((echo0000000000000000000000000000000000000042;-echo_without_newline0000000000000000000000000000000000000084;)\-|gitcat-file--batch-check)"+cat>expect<<\-EOF&&+0000000000000000000000000000000000000042missing+0000000000000000000000000000000000000084missing+EOF+echo0000000000000000000000000000000000000042;+echo_without_newline0000000000000000000000000000000000000084|\+gitcat-file--batch-check>actual&&+test_cmpexpectactual' test_expect_success"--batch for an existent and a non-existent hash"'-test"$tag_sha1 tag $tag_size+cat>expect<<\-EOF&&+tag_sha1tag$tag_size$tag_content-0000000000000000000000000000000000000000missing" = \-"$((echo$tag_sha1;-echo_without_newline0000000000000000000000000000000000000000;)\-|gitcat-file--batch)"+0000000000000000000000000000000000000000missing+EOF+echo$tag_sha1;echo_without_newline0000000000000000000000000000000000000000|\+gitcat-file--batch>actual&&+test_cmpexpect_actual' test_expect_success"--batch-check for an emtpy line"'-test" missing"="$(echo|gitcat-file--batch-check)"+echo" missing">expect&&+echo|gitcat-file--batch-check>actual&&+test_cmpexpectactual'batch_input="$hello_sha1
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
'git branch --help' will fail when git manpages aren't already
installed; now that its status is tested, guard these instances with
'test_might_fail'.
Acked-by: Jonathan Nieder <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t3200-branch.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
@@ -22,7 +22,7 @@ test_expect_success \ test_expect_success\'git branch --help should not have created a bogus branch''-gitbranch--help</dev/null>/dev/null2>/dev/null;+test_might_failgitbranch--help</dev/null>/dev/null2>/dev/null&&test_path_is_missing.git/refs/heads/--help'
@@ -88,7 +88,7 @@ test_expect_success \ test_expect_success\'git branch -m n/n n should work'\'gitbranch-ln/n&&-gitbranch-mn/nn+gitbranch-mn/nn&&test_path_is_file.git/logs/refs/heads/n' test_expect_success'git branch -m o/o o should fail when o/p exists''
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix these breaks.
'unset' returns non-zero status when the variable passed was already
unset on some shells; now that its status is tested, change these
instances to 'sane_unset'.
Acked-by: Jonathan Nieder <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t1501-worktree.sh | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
Breaks in a test assertion's && chain can potentially hide failures
from earlier commands in the chain. Fix instances of this by adding
'&&' at the end of lines where they're missing; this patch doesn't
intend to make any other changes.
Acked-by: Jonathan Nieder <redacted>
Signed-off-by: Ramkumar Ramachandra <redacted>
---
t/t1007-hash-object.sh | 2 +-
t/t1013-loose-object-format.sh | 2 +-
t/t1300-repo-config.sh | 2 +-
t/t1412-reflog-loop.sh | 2 +-
t/t1510-repo-setup.sh | 4 ++--
t/t1511-rev-parse-caret.sh | 2 +-
t/t3310-notes-merge-manual-resolve.sh | 10 +++++-----
t/t3400-rebase.sh | 4 ++--
t/t3418-rebase-continue.sh | 4 ++--
t/t3419-rebase-patch-id.sh | 2 +-
10 files changed, 17 insertions(+), 17 deletions(-)
@@ -389,7 +389,7 @@ test_expect_success 'abort notes merge' 'test_must_faills.git/NOTES_MERGE_*>output2>/dev/null&&test_cmp/dev/nulloutput&&# m has not moved (still == y)-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -525,9 +525,9 @@ EOFtest-f.git/NOTES_MERGE_WORKTREE/$commit_sha3&&test-f.git/NOTES_MERGE_WORKTREE/$commit_sha4&&# Refs are unchanged-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"-test"$(gitrev-parserefs/notes/y)"="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"-test"$(gitrev-parserefs/notes/m)"!="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"+test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&+test"$(gitrev-parserefs/notes/y)"="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&+test"$(gitrev-parserefs/notes/m)"!="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&# Mention refs/notes/m, and its current and expected value in outputgrep-q"refs/notes/m"output&&grep-q"$(gitrev-parserefs/notes/m)"output&&
@@ -545,7 +545,7 @@ test_expect_success 'resolve situation by aborting the notes merge' 'test_must_faills.git/NOTES_MERGE_*>output2>/dev/null&&test_cmp/dev/nulloutput&&# m has not moved (still == w)-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"+test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -172,8 +172,8 @@ test_expect_success 'fail when upstream arg is missing and not configured' ' test_expect_success'default to @{upstream} when upstream arg is missing''gitcheckout-bdefaulttopic&&-gitconfigbranch.default.remote.-gitconfigbranch.default.mergerefs/heads/master+gitconfigbranch.default.remote.&&+gitconfigbranch.default.mergerefs/heads/master&&gitrebase&&test"$(gitrev-parsedefault~1)"="$(gitrev-parsemaster)"'
Hi,
My OPT_SUBCOMMAND idea crashed and burned; I decided to salvage some
of the work that went into improving the git-bundle builtin and put it
into another series along with some additional tests. I hope this
benefits people who use git-bundle to do incremental backups on their
servers or otherwise.
A couple of thoughts:
1. There's a SP between the OBJID and the ref name in list-heads as
opposed to the TAB used by other git commands such as ls-remote,
diff-tree. Will fixing it break someone's parser somewhere?
2. Is it worth fixing the "--stdin" tests? What is the usecase? A
quick blame points to f62e0a39 (t5704 (bundle): add tests for bundle
--stdin, 2010-04-19): Jonathan, Joey?
Cheers.
-- Ram
Ramkumar Ramachandra (2):
t5704 (bundle): rewrite for larger coverage
bundle: rewrite builtin to use parse-options
builtin/bundle.c | 91 +++++++++++++++++++++++++++++---------------------
t/t5704-bundle.sh | 95 ++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 122 insertions(+), 64 deletions(-)
--
1.7.4.1
The git-bundle builtin currently parses command-line options by hand;
this is fragile, and reports cryptic errors on failure. Use the
parse-options library to do the parsing instead.
Encouraged-by: Jonathan Nieder [off-list ref]
Signed-off-by: Ramkumar Ramachandra <redacted>
---
builtin/bundle.c | 91 +++++++++++++++++++++++++++++++----------------------
t/t5704-bundle.sh | 2 +-
2 files changed, 54 insertions(+), 39 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:39
Hi Ram,
Ramkumar Ramachandra wrote:
1. There's a SP between the OBJID and the ref name in list-heads as
opposed to the TAB used by other git commands such as ls-remote,
diff-tree. Will fixing it break someone's parser somewhere?
I don't know. Would there be any advantage at all to changing the
output format of the tool? Bad idea.
If the goal is to avoid confusion, perhaps a note in the documentation
would help.
2. Is it worth fixing the "--stdin" tests? What is the usecase?
Is "script that wants to list which revs to bundle, possibly exceeding
the command-line length limit" not enough of a use case? Yes, I think
it is very much worth fixing.
Thanks for looking at this.
Jonathan
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:39
Hi,
Ramkumar Ramachandra wrote:
Rewrite
Always a scary word. Very rarely justified, especially when the
original and rewritten versions of something are not going to be able
to coexist for a period while the bugs are ironed out. It doesn't
leave me optimistic.
the git-bundle testsuite to exercise more of its
functionality.
Luckily, this goal suggests that I am going to see some new tests
added, without the existing coverage being removed or mangled, so
maybe I can ignore the fears awakened by the word "Rewrite". Let's
see...
[...]
quoted hunk
--- a/t/t5704-bundle.sh+++ b/t/t5704-bundle.sh
@@ -1,56 +1,99 @@#!/bin/sh-test_description='some bundle related tests'+test_description='Test git-bundle'
No explicit tags in the setup this time. Now all commits are referred
to by tags, which worsens the coverage, since if some future change
caused commits not referred to by a tag to be dropped, it would be
missed. Paraphrasing
>file &&
git add file &&
test_tick &&
git commit -m initial &&
git tag -m initial initial
to
test_commit initial file
when not preparing to make some other change in the same place and if
the original was not too confusing feels like gratuitous churn.
[...]
A new test. What assertion is it testing? Why censor out the
object names when comparing the expected object names to the
actual ones, instead of computing the appropriate object names
for the expected result? Is this new test useful, or does it
cover ground already tested in t5510-fetch.sh?
+test_expect_success 'verify succeeds' '
+ git bundle create bundle second third &&
+ git bundle verify bundle
'
A test for "git bundle verify" is a welcome addition.
Based on 'git grep -e "git bundle list-heads" -- t', there don't seem
to be any existing tests for "git bundle list-heads" except for
t5510-fetch.sh, but I'm not sure what this adds on top of that one.
-test_expect_success 'tags can be excluded by rev-list options' '
-
- git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
- git ls-remote bundle > output &&
- ! grep tag output
In this case, "stray command-line arguments" actually means "extra
arguments to 'verify'", I guess?
What happens if I run "git bundle verify *.bundle" in a directory
with multiple bundles? What should happen?
I don't understand what "options to narrow refs" means. Does that
mean options like --remotes=origin which yield refs from some subset
of the ref namespace, unlike --all?
[...]
+test_expect_success 'unbundle succeeds' '
A test for "git bundle unbundle" is a welcome addition.
[...]
Seems like a gratuitous change to mix into a patch that introduces
functional changes.
I found this hard to review, since it doesn't seem very focussed ---
it mixes style cleanups, removal of code, and introduction of new
code. I'd be way happier to see a new patch that just adds new tests
to the script without potentially breaking anything on the way. Then
if the style cleanups still seem important to you, they can be
reviewed as a separate patch.
Hoping that clarifies a little,
Jonathan
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:52:39
Ramkumar Ramachandra wrote:
The git-bundle builtin currently parses command-line options by hand;
this is fragile, and reports cryptic errors on failure. Use the
parse-options library to do the parsing instead.
I don't understand how this is fragile. I haven't actually run into
error messages from "git bundle" I found to be cryptic, but if they
are, they surely can be improved locally. Could you give an example
or something?
Encouraged-by: Jonathan Nieder [off-list ref]
No, not encouraged.
But parseoptification does have some nice benefits, so let's see how
the patch looks...
[...]
No, just no. Using parse-options with an empty option table is
complete overkill for handling the "-h" option. Without a lot more
justification, this doesn't make it seem more sane or readable at all.
Stopping here. I wouldn't mind seeing "git bundle" being
parseoptified, but not if the result looks like this.
I _do_ think that a systematic option-parsing library that handles
subcommands would be something possible and probably useful for git.
Its input might include a table with subcommand names, an option table
for each, and a function to call when that subcommand is used:
struct parseopt_subcommand subcmds[] = {
{ "list", no_options, notes_list },
{ "add", add_options, notes_add },
{ "copy", copy_options, notes_copy },
{ "append", append_options, notes_append },
{ "edit", no_options, notes_edit },
{ "show", no_options, notes_show },
...
};
Then "git notes -h" might be able to automatically generate a table of
synopses, and "gite notes --help-all" might print help for all
subcommands. Something like that.
Hope that helps,
Jonathan