Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-24 Thread Paul Tan
On Mon, Mar 23, 2015 at 6:18 PM, Duy Nguyen pclo...@gmail.com wrote:
 Could you share these changes? I'm just wondering if we can add kcov
 support to the test suite.

In this case it's more of an embarrassing hack, as I just needed a way
to make git run kcov outdir git-pull.sh whenever git pull is called
since kcov will not instrument any spawned subprocesses. I modified
execv_dashed_external() in git.c to prepend kcov to argv (diff
probably munged by gmail):

diff --git a/git.c b/git.c
index 8c7ee9c..0f8e7d4 100644
--- a/git.c
+++ b/git.c
@@ -536,6 +536,8 @@ static void execv_dashed_external(const char **argv)
struct strbuf cmd = STRBUF_INIT;
const char *tmp;
int status;
+   struct argv_array args = ARGV_ARRAY_INIT;
+   int i;

if (use_pager == -1)
use_pager = check_pager_config(argv[0]);
@@ -551,6 +553,11 @@ static void execv_dashed_external(const char **argv)
 */
tmp = argv[0];
argv[0] = cmd.buf;
+   argv_array_push(args, kcov);
+   argv_array_push(args, /home/pyokagan/pyk/git/kcov);
+   argv_array_push(args, cmd.buf);
+   for (i = 1; argv[i]; i++)
+   argv_array_push(args, argv[i]);

trace_argv_printf(argv, trace: exec:);

@@ -558,7 +565,7 @@ static void execv_dashed_external(const char **argv)
 * if we fail because the command is not found, it is
 * OK to return. Otherwise, we just pass along the status code.
 */
-   status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE |
RUN_CLEAN_ON_EXIT);
+   status = run_command_v_opt(args.argv, RUN_SILENT_EXEC_FAILURE
| RUN_CLEAN_ON_EXIT);
if (status = 0 || errno != ENOENT)
exit(status);

I'm guessing a real solution is to follow what the test suite does for
the --valgrind option, though I haven't looked into it in detail.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-23 Thread Johannes Schindelin
Hi Paul,

On 2015-03-22 18:39, Paul Tan wrote:

 The code coverage tools can help here as well. The kcov output clearly
 shows which options of git-pull are currently not being tested. But
 yes, I agree that the test suite shouldn't be relied too much on
 compared to code inspection and review.

Fully agree.

 On another important topic, though, along with git-pull.sh, I'm
 looking for another script to convert in parallel with git-pull.sh so
 that there will be no blocks due to patch review. Generally, I think
 rewriting scripts that are called frequently by users, or spawn a lot
 of processes due to loops, would be most desirable because the runtime
 gains would be much higher. A quick review of the scripts shows that
 git-am.sh, git-rebase--interactive.sh and git-quiltimport.sh have
 pretty heavy loops with lots of process spawning that grows with
 input.
 
 I'm currently leaning with git-am because not only is it a frequently
 used command, git-rebase--am.sh (for non-interactive rebase) calls it
 as well. In fact, quick tests show that it takes up 98% of
 git-rebase's execution time on Windows, so if git-am's performance
 improves it would be a huge win on many fronts. git-am's code also
 seems to be manageable for a 3-month project.

Yeah, `git am` is definitely a good pick.

Thanks!
Johannes

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-23 Thread Duy Nguyen
On Sat, Mar 21, 2015 at 8:23 PM, Paul Tan pyoka...@gmail.com wrote:
 I see git already has gcov support. For shell scripts, maybe kcov[1]
 could be used. With some slight code changes, I managed to generate a
 report for the git-pull tests[2] which should at least provide a good
 starting point for how the tests can be improved.

Could you share these changes? I'm just wondering if we can add kcov
support to the test suite.

 [1] http://simonkagstrom.github.io/kcov/
 [2] 
 http://www.googledrive.com/host/0B4O2AiYulllpfmJlTW4xT050OVVicnNWWS02dm52aTJ2TFIwQ2QwdWh0VHotSkU4eUNNWjg

At least we can see [3] that not many options in git-pull is executed.
Cool reports.

[3] 
https://83dc3588620c5a97164396ec753a2fa480f6a7b0-www.googledrive.com/host/0B4O2AiYulllpfmJlTW4xT050OVVicnNWWS02dm52aTJ2TFIwQ2QwdWh0VHotSkU4eUNNWjg/git-pull/git-pull.360f32c2.html

-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-22 Thread Paul Tan
Hi,

On Sun, Mar 22, 2015 at 1:35 AM, Johannes Schindelin
johannes.schinde...@gmx.de wrote:
 Maybe code coverage tools could help here so we only need to focus on
 the code paths that are untested by the test suite. At the minimum,
 all of the non-trivial code paths in both the shell script and the
 converted builtin must be covered by tests. This should help to
 eliminate most sources of breakages. Anything further than that would
 require an experienced understanding of all the possible important
 inputs to be tested, which I personally feel would make the project
 quite tedious.

 I see git already has gcov support. For shell scripts, maybe kcov[1]
 could be used. With some slight code changes, I managed to generate a
 report for the git-pull tests[2] which should at least provide a good
 starting point for how the tests can be improved.

 While it is often a tempting idea to make test suites as thorough as 
 possible, there lies a true danger herein. True war story: in one of the 
 projects I was involved in, the test suite grew to a size that one complete 
 run lasted two weeks. Yes, that is fourteen days. Needless to say: this test 
 suite was run rarely. How useful is a test suite that is run rarely? More 
 useful than a non-existent one, to be sure, but it is still more of a burden 
 than a boon.

 Now, on Windows the test suite takes almost three hours to run. This really, 
 really slows down development.

 So while we are not yet at the too large to be useful state, I would 
 caution against trying to get there.

 Instead, I would really like to focus on the *usage*. Calling `git grep git 
 pull t/` should give you an idea what usage of `git pull` is already tested. 
 It should be pretty easy to come up with a list of *common* use cases, and if 
 any of them are not covered, adding tests for them is simple and 
 straight-forward, too.

The code coverage tools can help here as well. The kcov output clearly
shows which options of git-pull are currently not being tested. But
yes, I agree that the test suite shouldn't be relied too much on
compared to code inspection and review.

On another important topic, though, along with git-pull.sh, I'm
looking for another script to convert in parallel with git-pull.sh so
that there will be no blocks due to patch review. Generally, I think
rewriting scripts that are called frequently by users, or spawn a lot
of processes due to loops, would be most desirable because the runtime
gains would be much higher. A quick review of the scripts shows that
git-am.sh, git-rebase--interactive.sh and git-quiltimport.sh have
pretty heavy loops with lots of process spawning that grows with
input.

I'm currently leaning with git-am because not only is it a frequently
used command, git-rebase--am.sh (for non-interactive rebase) calls it
as well. In fact, quick tests show that it takes up 98% of
git-rebase's execution time on Windows, so if git-am's performance
improves it would be a huge win on many fronts. git-am's code also
seems to be manageable for a 3-month project.

Anyway, I would like to know if you (or anyone else) have any scripts in mind.

(I also think that just 2 scripts would be enough to fill the 3
months, but that might be me just being too conservative)

Regards,
Paul
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-21 Thread Johannes Schindelin
Hi Paul,

On 2015-03-21 15:00, Paul Tan wrote:

 Thanks for your suggestions, I agree with most of them :).
 
 On Wed, Mar 18, 2015 at 5:00 PM, Johannes Schindelin
 johannes.schinde...@gmx.de wrote:
 +static int parse_opt_rebase(const struct option *opt, const char
 *arg, int unset)
 +{
 + if (arg)
 + *(int *)opt-value = parse_rebase(arg);
 + else
 + *(int *)opt-value = unset ? REBASE_FALSE : REBASE_TRUE;
 + return (*(int *)opt-value) = 0 ? 0 : -1;
 +}

 In this function (and also in other places below), there is this pattern 
 that a `struct option` pointer is passed to the function, but then only 
 `*(int *)opt-value` is written to. Therefore, I would suggest to change the 
 signature of the function and pass `(int *)opt-value` as function parameter.
 
 It's used as a callback for the argument parser though, so the
 callback signature is required.

Good point ;-)

For readability, I would then suggest to declare `int *result = (int 
*)opt-value;` on the top of the function and then use `*result = ...` later.

 +static int has_unstaged_changes(void)

 Yeah, this function, as well as the ones below it, look as if they are so 
 common that they *should* be already somewhere in libgit.a. But I did not 
 find them, either...

 Of course it *would* be nice to identify places where essentially the same 
 code is needed, and refactor accordingly. But I think that is outside the 
 scope of this project.
 
 Actually, I think that identifying the places where code can be
 trivially shared (without requiring major refactoring) should be part
 of the project, otherwise lots of code may be duplicated and cause
 code bloat. The obvious one would be fork_point() in this patch, which
 is copied from the merge-base builtin and not accessible because it
 has static linkage. The project should, at the very least, allow the
 function to be shared between git-pull and git-merge-base, as well as
 to modify the function so that it can fail without die()-ing.

Yes, I agree wholeheartedly. But I like your choice to strike a balance for the 
sake of a proof-of-concept.

Ciao,
Johannes
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-21 Thread Johannes Schindelin
Hi Paul,

On 2015-03-21 14:23, Paul Tan wrote:

 Thanks for the review, though I would like to work on the proposal now
 before the deadline passes :)

That makes sense.

 On Thu, Mar 19, 2015 at 1:52 AM, Matthieu Moy
 matthieu@grenoble-inp.fr wrote:
 Paul Tan pyoka...@gmail.com writes:

 Ideally, I think the solution is to
 improve the test suite and make it as comprehensive as possible, but
 writing a comprehensive test suite may be too time consuming.

 time-consuming, but also very beneficial since the code would end up
 being better tested. For sure, a rewrite is a good way to break stuff,
 but anything untested can also be broken by mistake rather easily at any
 time.

 I'd suggest doing a bit of manual mutation testing: take your C code,
 comment-out a few lines of code, see if the tests still pass, and if
 they do, add a failing test that passes again once you uncomment the
 code.
 
 Maybe code coverage tools could help here so we only need to focus on
 the code paths that are untested by the test suite. At the minimum,
 all of the non-trivial code paths in both the shell script and the
 converted builtin must be covered by tests. This should help to
 eliminate most sources of breakages. Anything further than that would
 require an experienced understanding of all the possible important
 inputs to be tested, which I personally feel would make the project
 quite tedious.
 
 I see git already has gcov support. For shell scripts, maybe kcov[1]
 could be used. With some slight code changes, I managed to generate a
 report for the git-pull tests[2] which should at least provide a good
 starting point for how the tests can be improved.

While it is often a tempting idea to make test suites as thorough as possible, 
there lies a true danger herein. True war story: in one of the projects I was 
involved in, the test suite grew to a size that one complete run lasted two 
weeks. Yes, that is fourteen days. Needless to say: this test suite was run 
rarely. How useful is a test suite that is run rarely? More useful than a 
non-existent one, to be sure, but it is still more of a burden than a boon.

Now, on Windows the test suite takes almost three hours to run. This really, 
really slows down development.

So while we are not yet at the too large to be useful state, I would caution 
against trying to get there.

Instead, I would really like to focus on the *usage*. Calling `git grep git 
pull t/` should give you an idea what usage of `git pull` is already tested. 
It should be pretty easy to come up with a list of *common* use cases, and if 
any of them are not covered, adding tests for them is simple and 
straight-forward, too.

Ciao,
Johannes
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-21 Thread Paul Tan
Hi,

On Thu, Mar 19, 2015 at 6:26 AM, Junio C Hamano gits...@pobox.com wrote:
 Paul Tan pyoka...@gmail.com writes:

 +/* Global vars since they are used often */
 +static char *head_name;
 +static const char *head_name_short;
 +static unsigned char head_sha1[20];
 +static int head_flags;
 +
 +enum rebase_type {
 + REBASE_FALSE = 0,
 + REBASE_TRUE = 1,
 + REBASE_PRESERVE = 2
 +};
 +
 +/**
 + * Parse rebase config/option value and return corresponding int
 + */
 +static int parse_rebase(const char *arg)
 +{
 + if (!strcmp(arg, true))
 + return REBASE_TRUE;
 + else if (!strcmp(arg, false))
 + return REBASE_FALSE;
 + else if (!strcmp(arg, preserve))
 + return REBASE_PRESERVE;
 + else
 + return -1; /* Invalid value */
 +}

 Even though the original does not use bool-or-string-config, we
 would want to do the same by doing something like

 case (config_maybe_bool()) {
 case 0:
 return REBASE_FALSE;
 case 1:
 return REBASE_TRUE;
 default:
 if (!strcmp(arg, preserve))
 return REBASE_PRESERVE;
 return -1;
 }

 and then use that in rebase_config_default().

If you mean letting yes, on, no, off be accepted on the
command line as well, then yes I guess it will be a good idea.


 +
 +/**
 + * Returns default rebase option value
 + */
 +static int rebase_config_default(void)
 +{
 + struct strbuf name = STRBUF_INIT;
 + const char *value = NULL;
 + int boolval;
 +
 + strbuf_addf(name, branch.%s.rebase, head_name_short);
 + if (git_config_get_value(name.buf, value))
 + git_config_get_value(pull.rebase, value);

 What happens when neither is defined?

 + strbuf_release(name);
 + if (!value)
 + return REBASE_FALSE;

 Hmph, are you sure about this?  Isn't this [pull] rebase that does
 not have = value, in which case pull.rebase is true?

 You cannot use NULL as the sentinel value to tell that you did not
 find either branch.*.rebase nor pull.rebase (in which case you want
 to default to 'false').  Either of them can be spelled as an
 equal-less true, which you will see as value==NULL, and you want to
 take that as 'true'.

 const char *value = false;
 ...
 if (get_value(..., value))
 get_value(..., value));
 strbuf_release(name);
 if (!value)
 return REBASE_TRUE;
 return parse_rebase(value);

 or something along that line, perhaps?

Whoops, didn't take into account the possibility that the config value
could be NULL. Thanks.


 + boolval = git_config_maybe_bool(pull.rebase, value);
 + if (boolval = 0)
 + return boolval ? REBASE_TRUE : REBASE_FALSE;
 + else if (value  !strcmp(value, preserve))
 + return REBASE_PRESERVE;

 Is value something you need to free before returning from this
 function?

From my reading if config.c, the memory of value comes from the
config_set the_config_set (the config cache), so there is no need to
free it.


 +static int parse_opt_recurse_submodules(const struct option *opt, const 
 char *arg, int unset)
 +{
 + if (!arg)
 + *(int *)opt-value = unset ? RS_NO : RS_YES;
 + else if (!strcmp(arg, no))
 + *(int *)opt-value = RS_NO;
 + else if (!strcmp(arg, yes))
 + *(int *)opt-value = RS_YES;
 + else if (!strcmp(arg, on-demand))
 + *(int *)opt-value = RS_ON_DEMAND;
 + else
 + return -1;
 + return 0;

 I suspect that maybe-bool-or-string comment applies equally here for
 the UI consistency.

Yup, I'll keep that in mind.

 I'll stop here for now.  Thanks.

Thanks.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-21 Thread Paul Tan
Hi,

Thanks for the review, though I would like to work on the proposal now
before the deadline passes :)

On Thu, Mar 19, 2015 at 1:52 AM, Matthieu Moy
matthieu@grenoble-inp.fr wrote:
 Paul Tan pyoka...@gmail.com writes:

 Ideally, I think the solution is to
 improve the test suite and make it as comprehensive as possible, but
 writing a comprehensive test suite may be too time consuming.

 time-consuming, but also very beneficial since the code would end up
 being better tested. For sure, a rewrite is a good way to break stuff,
 but anything untested can also be broken by mistake rather easily at any
 time.

 I'd suggest doing a bit of manual mutation testing: take your C code,
 comment-out a few lines of code, see if the tests still pass, and if
 they do, add a failing test that passes again once you uncomment the
 code.

Maybe code coverage tools could help here so we only need to focus on
the code paths that are untested by the test suite. At the minimum,
all of the non-trivial code paths in both the shell script and the
converted builtin must be covered by tests. This should help to
eliminate most sources of breakages. Anything further than that would
require an experienced understanding of all the possible important
inputs to be tested, which I personally feel would make the project
quite tedious.

I see git already has gcov support. For shell scripts, maybe kcov[1]
could be used. With some slight code changes, I managed to generate a
report for the git-pull tests[2] which should at least provide a good
starting point for how the tests can be improved.

[1] http://simonkagstrom.github.io/kcov/
[2] 
http://www.googledrive.com/host/0B4O2AiYulllpfmJlTW4xT050OVVicnNWWS02dm52aTJ2TFIwQ2QwdWh0VHotSkU4eUNNWjg

Regards,
Paul
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-21 Thread Paul Tan
Hi,

Thanks for your suggestions, I agree with most of them :).

On Wed, Mar 18, 2015 at 5:00 PM, Johannes Schindelin
johannes.schinde...@gmx.de wrote:
 +static int parse_opt_rebase(const struct option *opt, const char
 *arg, int unset)
 +{
 + if (arg)
 + *(int *)opt-value = parse_rebase(arg);
 + else
 + *(int *)opt-value = unset ? REBASE_FALSE : REBASE_TRUE;
 + return (*(int *)opt-value) = 0 ? 0 : -1;
 +}

 In this function (and also in other places below), there is this pattern that 
 a `struct option` pointer is passed to the function, but then only `*(int 
 *)opt-value` is written to. Therefore, I would suggest to change the 
 signature of the function and pass `(int *)opt-value` as function parameter.

It's used as a callback for the argument parser though, so the
callback signature is required.


 +static int has_unstaged_changes(void)

 Yeah, this function, as well as the ones below it, look as if they are so 
 common that they *should* be already somewhere in libgit.a. But I did not 
 find them, either...

 Of course it *would* be nice to identify places where essentially the same 
 code is needed, and refactor accordingly. But I think that is outside the 
 scope of this project.

Actually, I think that identifying the places where code can be
trivially shared (without requiring major refactoring) should be part
of the project, otherwise lots of code may be duplicated and cause
code bloat. The obvious one would be fork_point() in this patch, which
is copied from the merge-base builtin and not accessible because it
has static linkage. The project should, at the very least, allow the
function to be shared between git-pull and git-merge-base, as well as
to modify the function so that it can fail without die()-ing.

Regards,
Paul
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-18 Thread Stephen Robin

 Paul Tan writes:
 I would like to share this very rough prototype with everyone. 
...
 I started this as a just-for-fun exercise to learn about the git internal
API

I started to rewrite git-pull for similar reasons a couple of months ago,
but I haven't had time to complete it.  It looks like my version has less
work remaining than yours, would you like me to share it?

 Finally, there is the possibility that in the process of conversion bugs
or incompatible behavioral changes may be introduced which are not caught by
the test suite. Ideally, I think the solution is to improve the test suite
and make it as comprehensive as possible, but writing a comprehensive test
suite may be too time consuming. 

This is why I haven't had time to finish and submit my patch.  While the c
code is pretty much complete, I felt the test suite needed some extension
before I could be confident the new code is correct.



--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-18 Thread Johannes Schindelin
Hi Stephen,

On 2015-03-18 09:38, Stephen Robin wrote:
 Paul Tan writes:
 I would like to share this very rough prototype with everyone.
 ...
 I started this as a just-for-fun exercise to learn about the git internal
 API
 
 I started to rewrite git-pull for similar reasons a couple of months ago,
 but I haven't had time to complete it.  It looks like my version has less
 work remaining than yours, would you like me to share it?

Hmm. It always results in an unnecessary round trip if you ask people to ask 
you to share it.

At this point, because Paul already made his work public, I would say that we 
should continue with his version. Please understand this as an encouragement 
for the future to share your code pro-actively, just like Git's own source code 
has been shared with you without the need for you to request it explicitly.

For the record, Duy also already shared his C code to implement `git pull` in C 
publicly. I think that Paul decided to start again in order to understand every 
detail of the process of converting a shell script into a builtin; If that was 
the rationale, I would agree that it is a wise one.

Ciao,
Johannes
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-18 Thread Johannes Schindelin
Hi Paul,

thank you for this very detailed mail. It was a real pleasure to read this 
well-researched document.

In the following, I will pick out only parts from the mail, in the interest of 
both of our time. Please assume that I agree with everything that I do not 
quote below (and even the with quoted parts I agree mostly ;-)).

On 2015-03-17 14:57, Paul Tan wrote:

 on Windows the runtime fell from 8m 25s to 1m 3s.

This is *exactly* the type of benefit that makes this project so important! 
Nice one.

 A simpler, but less perfect strategy might be to just convert the shell
 scripts directly statement by statement to C, using the run_command*()
 functions as Duy Nguyen[2] suggested, before changing the code to use
 the internal API.

Yeah, the idea is to have a straight-forward strategy to convert the scripts in 
as efficient manner as possible. It also makes reviewing easier if the first 
step is an almost one-to-one translation to `run_command*()`-based builtins.

Plus, it is rewarding to have concise steps that can be completed in a timely 
manner.


 +/* NOTE: git-pull.sh only supports --log and --no-log, as opposed to what
 + * man git-pull says. */
 +static int opt_shortlog_len;

This comment might want to live in the commit message instead... It is prone to 
get stale in the code while it will always be correct (and easier to spot) in 
the commit message.

 +/**
 + * Returns default rebase option value
 + */
 +static int rebase_config_default(void)
 +{
 + struct strbuf name = STRBUF_INIT;
 + const char *value = NULL;
 + int boolval;
 +
 + strbuf_addf(name, branch.%s.rebase, head_name_short);
 + if (git_config_get_value(name.buf, value))
 + git_config_get_value(pull.rebase, value);
 + strbuf_release(name);
 + if (!value)
 + return REBASE_FALSE;
 + boolval = git_config_maybe_bool(pull.rebase, value);
 + if (boolval = 0)
 + return boolval ? REBASE_TRUE : REBASE_FALSE;
 + else if (value  !strcmp(value, preserve))
 + return REBASE_PRESERVE;
 + die(_(invalid value for branch.%s.rebase \%s\), head_name_short, 
 value);
 +}

Personally, I would use a couple of empty lines for enhanced structure. 
Conceptually, there are four parts: the variable declarations, querying the 
config, parsing the value, and `die()`ing in case of error. There is already an 
empty line between the first two parts, and I would imagine that readability 
would be improved further by having an empty line after the `strbuf_release()` 
and the `return REBASE_PRESERVE` statement, respectively.

 +static int parse_opt_rebase(const struct option *opt, const char
 *arg, int unset)
 +{
 + if (arg)
 + *(int *)opt-value = parse_rebase(arg);
 + else
 + *(int *)opt-value = unset ? REBASE_FALSE : REBASE_TRUE;
 + return (*(int *)opt-value) = 0 ? 0 : -1;
 +}

In this function (and also in other places below), there is this pattern that a 
`struct option` pointer is passed to the function, but then only `*(int 
*)opt-value` is written to. Therefore, I would suggest to change the signature 
of the function and pass `(int *)opt-value` as function parameter.

 +static int has_unstaged_changes(void)

Yeah, this function, as well as the ones below it, look as if they are so 
common that they *should* be already somewhere in libgit.a. But I did not find 
them, either...

Of course it *would* be nice to identify places where essentially the same code 
is needed, and refactor accordingly. But I think that is outside the scope of 
this project.

The rest looks pretty good (and you realize that my comments above are really 
more nit picks than anything else).

The FIXMEs should be relatively easy to address. It would be my pleasure to 
work with you.

Ciao,
Johannes
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-18 Thread Matthieu Moy
Hi,

First of all, thanks a lot for working on this. I'm rather impressed to
see a working proof of concept so soon! And impressed by the quality for
a first draft.

A few minor remaks below after a very quick look.

Paul Tan pyoka...@gmail.com writes:

 Ideally, I think the solution is to
 improve the test suite and make it as comprehensive as possible, but
 writing a comprehensive test suite may be too time consuming.

time-consuming, but also very beneficial since the code would end up
being better tested. For sure, a rewrite is a good way to break stuff,
but anything untested can also be broken by mistake rather easily at any
time.

I'd suggest doing a bit of manual mutation testing: take your C code,
comment-out a few lines of code, see if the tests still pass, and if
they do, add a failing test that passes again once you uncomment the
code.

 diff --git a/Makefile b/Makefile
 index 44f1dd1..50a6a16 100644
 --- a/Makefile
 +++ b/Makefile
 @@ -470,7 +470,6 @@ SCRIPT_SH += git-merge-octopus.sh
  SCRIPT_SH += git-merge-one-file.sh
  SCRIPT_SH += git-merge-resolve.sh
  SCRIPT_SH += git-mergetool.sh
 -SCRIPT_SH += git-pull.sh

When converting a script into a builtin, we usually move the old script
to contrib/examples/.

 +static const char * const builtin_pull_usage[] = {
 + N_(git pull [-n | --no-stat] [--[no-]commit] [--[no-]squash] 
 [--[no-]ff|--ff-only] [--[no-]rebase|--rebase=preserve] [-s strategy]... 
 [fetch-options] repo head...),

I know we have many instances of very long lines for usage string, but
it would be better IMHO to wrap it both in the code and in the output of
git pull -h.

 +/* NOTE: git-pull.sh only supports --log and --no-log, as opposed to what
 + * man git-pull says. */

We usually write multi-line comments

/*
 * like
 * this
 */

 +/* Global vars since they are used often */

Being use often does not count as an excuse for being global IMHO.
Having global variables means you share the same instance in several
functions, and you have to be careful with things like

void g()
{
glob = bar;
}

void f()
{
glob = foo;
g();
bar = glob;
}

As a reader, I'd rather not have to be careful about this to keep my
neurons free for other things.

 +static char *head_name;

Actually, this one is used only in one function, so often is not even
true ;-).

 +static struct option builtin_pull_options[] = {

You may also declare this as local in cmd_pull().

 +/**
 + * Returns remote for branch

Here and elsewhere: use imperative (return, not return_s_). The comment
asks the function to return a value.

 + strbuf_addf(key, branch.%s.remote, branch);
 + git_config_get_value(key.buf, remote);
 + strbuf_release(key);

This config API is beautiful :-).

(Before last year's GSoC, you'd have needed ~10 lines of code to do the
same thing)

 + return error(Ambiguous refname: '%s', ref);

Here and elsewhere: don't forget to mark strings for translation.

 +/**
 + * Appends FETCH_HEAD's merge heads into arr. Returns number of merge heads,
 + * or -1 on error.
 + */
 +static int sha1_array_append_fetch_merge_heads(struct sha1_array *arr)
 +{
 + int num_heads = 0;
 + char *filename = git_path(FETCH_HEAD);
 + FILE *fp = fopen(filename, r);

I guess this is one instance where we could avoid writting (fetch) and
then parsing (here) if we had a better internal API.

But that can come after, of course.

 +}
 +
 +
 +static void argv_array_push_merge_args(struct argv_array *arr,

Bikeshed: you sometimes have two blank lines between functions,
sometimes one. Not sure it's intended.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC/GSOC] make git-pull a builtin

2015-03-18 Thread Junio C Hamano
Paul Tan pyoka...@gmail.com writes:

 +/* Global vars since they are used often */
 +static char *head_name;
 +static const char *head_name_short;
 +static unsigned char head_sha1[20];
 +static int head_flags;
 +
 +enum rebase_type {
 + REBASE_FALSE = 0,
 + REBASE_TRUE = 1,
 + REBASE_PRESERVE = 2
 +};
 +
 +/**
 + * Parse rebase config/option value and return corresponding int
 + */
 +static int parse_rebase(const char *arg)
 +{
 + if (!strcmp(arg, true))
 + return REBASE_TRUE;
 + else if (!strcmp(arg, false))
 + return REBASE_FALSE;
 + else if (!strcmp(arg, preserve))
 + return REBASE_PRESERVE;
 + else
 + return -1; /* Invalid value */
 +}

Even though the original does not use bool-or-string-config, we
would want to do the same by doing something like

case (config_maybe_bool()) {
case 0:
return REBASE_FALSE;
case 1:
return REBASE_TRUE;
default:
if (!strcmp(arg, preserve))
return REBASE_PRESERVE;
return -1;
}

and then use that in rebase_config_default().

 +
 +/**
 + * Returns default rebase option value
 + */
 +static int rebase_config_default(void)
 +{
 + struct strbuf name = STRBUF_INIT;
 + const char *value = NULL;
 + int boolval;
 +
 + strbuf_addf(name, branch.%s.rebase, head_name_short);
 + if (git_config_get_value(name.buf, value))
 + git_config_get_value(pull.rebase, value);

What happens when neither is defined?

 + strbuf_release(name);
 + if (!value)
 + return REBASE_FALSE;

Hmph, are you sure about this?  Isn't this [pull] rebase that does
not have = value, in which case pull.rebase is true?

You cannot use NULL as the sentinel value to tell that you did not
find either branch.*.rebase nor pull.rebase (in which case you want
to default to 'false').  Either of them can be spelled as an
equal-less true, which you will see as value==NULL, and you want to
take that as 'true'.

const char *value = false;
...
if (get_value(..., value))
get_value(..., value));
strbuf_release(name);
if (!value)
return REBASE_TRUE;
return parse_rebase(value);

or something along that line, perhaps?

 + boolval = git_config_maybe_bool(pull.rebase, value);
 + if (boolval = 0)
 + return boolval ? REBASE_TRUE : REBASE_FALSE;
 + else if (value  !strcmp(value, preserve))
 + return REBASE_PRESERVE;

Is value something you need to free before returning from this
function?

 +static int parse_opt_recurse_submodules(const struct option *opt, const char 
 *arg, int unset)
 +{
 + if (!arg)
 + *(int *)opt-value = unset ? RS_NO : RS_YES;
 + else if (!strcmp(arg, no))
 + *(int *)opt-value = RS_NO;
 + else if (!strcmp(arg, yes))
 + *(int *)opt-value = RS_YES;
 + else if (!strcmp(arg, on-demand))
 + *(int *)opt-value = RS_ON_DEMAND;
 + else
 + return -1;
 + return 0;

I suspect that maybe-bool-or-string comment applies equally here for
the UI consistency.

I'll stop here for now.  Thanks.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html