Re: [PATCH/RFC/GSoC 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-21 Thread Paul Tan
Hi Dscho,

(Sorry for the very late reply, I got caught up with some unexpected
work and am still clearing my inbox ><)

On Thu, Mar 17, 2016 at 1:11 AM, Johannes Schindelin
 wrote:
> On Wed, 16 Mar 2016, Paul Tan wrote:
>> On Wed, Mar 16, 2016 at 4:04 PM, Johannes Schindelin
>>  wrote:
>> > In addition I want to point out that sequencer's replay_opts seem to be at
>> > least related, but the patch shares none of its code with the sequencer.
>> > Let's avoid that.
>> >
>> > In other words, let's try to add as little code as possible when we can
>> > enhance existing code.
>>
>> Well, both git-rebase--am.sh and git-rebase--merge.sh do not use the
>> sequencer functionality at all, and we don't see git-am for example
>> needing to be aware of onto, orig-head, head-name etc.
>
> That is arguing that the implementation of --am and --merge is too far
> away from the sequencer and therefore should not be made closer.
>
> By that token, has_unstaged_changes() should never be allowed to call
> init_revisions(): it *never* looks at any revisions at all!
>
> And the idea of the sequencer is so much more related to --am and --merge
> than unstaged changes are to revisions: the entire purpose of the
> sequencer (no matter the *current* implementation with all its
> limitations) is to apply a bunch of patches, in sequence. That is pretty
> much precisely what *all* members of the rebase family are about.
>
> In other words: please do not let current limitations dictate that we
> should introduce diverging code for essentially the same workflow.

Ah, so you are thinking of replacing the --am and --merge scripts with
sequencer? That sounds great :-)

I'll wait for your sequencer patch series then.

Thanks!
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 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-20 Thread Stefan Beller
On Wed, Mar 16, 2016 at 5:04 AM, Paul Tan  wrote:
>>
>> How is this specific to the state file? All it does is create the
>> leading directory
>> if it doesn't exist? (So I'd expect file_exists(concat(dir, file)) to
>> have the same
>> result without actually creating the directory if it doesn't exist as
>> a side effect?
>
> I don't quite understand, AFAIK mkpath() does not create any
> directories as a side-effect. And yes, I just wanted a short way to
> say file_exists(concat(dir, file)) or file_exists(mkpath("%s/%s", dir,
> file)) without cluttering up the code.

My bad. I should not assume functions doing stuff as their name might suggest.
(It "makes the path" but only in terms of creating the right string, not on the
file system, where you'd use functions like safe_create_leading_directories.
I thought all that was implied in mkpath).

>
>> If the dir doesn't exist it can be created in rebase_options_load explicitly?
>
> I don't intend to create any directories if they do not exist.
>
>>> +
>>> +static int read_state_file(struct strbuf *sb, const char *dir, const char 
>>> *file)
>>> +{
>>> +   const char *path = mkpath("%s/%s", dir, file);
>>> +   strbuf_reset(sb);
>>> +   if (strbuf_read_file(sb, path, 0) >= 0)
>>> +   return sb->len;
>>> +   else
>>> +   return error(_("could not read '%s'"), path);
>>> +}
>>> +
>>> +int rebase_options_load(struct rebase_options *opts, const char *dir)
>>> +{
>>> +   struct strbuf sb = STRBUF_INIT;
>>> +   const char *filename;
>>> +
>>> +   /* opts->orig_refname */
>>> +   if (read_state_file(&sb, dir, "head-name") < 0)
>>> +   return -1;
>>> +   strbuf_trim(&sb);
>>> +   if (starts_with(sb.buf, "refs/heads/"))
>>> +   opts->orig_refname = strbuf_detach(&sb, NULL);
>>> +   else if (!strcmp(sb.buf, "detached HEAD"))
>>> +   opts->orig_refname = NULL;
>>> +   else
>>> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
>>> "head-name"));
>>> +
>>> +   /* opts->onto */
>>> +   if (read_state_file(&sb, dir, "onto") < 0)
>>> +   return -1;
>>> +   strbuf_trim(&sb);
>>> +   if (get_oid_hex(sb.buf, &opts->onto) < 0)
>>> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
>>> "onto"));
>>> +
>>> +   /*
>>> +* We always write to orig-head, but interactive rebase used to 
>>> write
>>> +* to head. Fall back to reading from head to cover for the case 
>>> that
>>> +* the user upgraded git with an ongoing interactive rebase.
>>> +*/
>>> +   filename = state_file_exists(dir, "orig-head") ? "orig-head" : 
>>> "head";
>>> +   if (read_state_file(&sb, dir, filename) < 0)
>>> +   return -1;
>>
>> So from here on we always use "orig-head" instead of "head" for
>> interactive rebase.
>> Would people ever rely on the (internal) file name and have e.g.
>> scripts which operate
>> on the "head" file ?
>
> This backwards-compatibility code is just a straight port from the
> code in git-rebase.sh.
>
> The usage of orig-head has been around since 2011 with 84df456
> (rebase: extract code for writing basic state, 2011-02-06), so I guess
> if people had issues with it, it would have been reported.

I did not read the rebase shell code, but commented on the C code only.
If this is already in there, let's keep it.
Sorry for the confusion.

Thanks,
Stefan
--
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 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-19 Thread Paul Tan
Hi Stefan,

On Tue, Mar 15, 2016 at 4:30 AM, Stefan Beller  wrote:
> On Sat, Mar 12, 2016 at 2:46 AM, Paul Tan  wrote:
>> These functions can be used for loading and saving common rebase options
>> into a state directory.
>>
>> Signed-off-by: Paul Tan 
>> ---
>>  rebase-common.c | 69 
>> +
>>  rebase-common.h |  4 
>>  2 files changed, 73 insertions(+)
>>
>> diff --git a/rebase-common.c b/rebase-common.c
>> index 5a49ac4..1835f08 100644
>> --- a/rebase-common.c
>> +++ b/rebase-common.c
>> @@ -26,3 +26,72 @@ void rebase_options_swap(struct rebase_options *dst, 
>> struct rebase_options *src)
>> *dst = *src;
>> *src = tmp;
>>  }
>> +
>> +static int state_file_exists(const char *dir, const char *file)
>> +{
>> +   return file_exists(mkpath("%s/%s", dir, file));
>> +}
>
> How is this specific to the state file? All it does is create the
> leading directory
> if it doesn't exist? (So I'd expect file_exists(concat(dir, file)) to
> have the same
> result without actually creating the directory if it doesn't exist as
> a side effect?

I don't quite understand, AFAIK mkpath() does not create any
directories as a side-effect. And yes, I just wanted a short way to
say file_exists(concat(dir, file)) or file_exists(mkpath("%s/%s", dir,
file)) without cluttering up the code.

> If the dir doesn't exist it can be created in rebase_options_load explicitly?

I don't intend to create any directories if they do not exist.

>> +
>> +static int read_state_file(struct strbuf *sb, const char *dir, const char 
>> *file)
>> +{
>> +   const char *path = mkpath("%s/%s", dir, file);
>> +   strbuf_reset(sb);
>> +   if (strbuf_read_file(sb, path, 0) >= 0)
>> +   return sb->len;
>> +   else
>> +   return error(_("could not read '%s'"), path);
>> +}
>> +
>> +int rebase_options_load(struct rebase_options *opts, const char *dir)
>> +{
>> +   struct strbuf sb = STRBUF_INIT;
>> +   const char *filename;
>> +
>> +   /* opts->orig_refname */
>> +   if (read_state_file(&sb, dir, "head-name") < 0)
>> +   return -1;
>> +   strbuf_trim(&sb);
>> +   if (starts_with(sb.buf, "refs/heads/"))
>> +   opts->orig_refname = strbuf_detach(&sb, NULL);
>> +   else if (!strcmp(sb.buf, "detached HEAD"))
>> +   opts->orig_refname = NULL;
>> +   else
>> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
>> "head-name"));
>> +
>> +   /* opts->onto */
>> +   if (read_state_file(&sb, dir, "onto") < 0)
>> +   return -1;
>> +   strbuf_trim(&sb);
>> +   if (get_oid_hex(sb.buf, &opts->onto) < 0)
>> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
>> "onto"));
>> +
>> +   /*
>> +* We always write to orig-head, but interactive rebase used to write
>> +* to head. Fall back to reading from head to cover for the case that
>> +* the user upgraded git with an ongoing interactive rebase.
>> +*/
>> +   filename = state_file_exists(dir, "orig-head") ? "orig-head" : 
>> "head";
>> +   if (read_state_file(&sb, dir, filename) < 0)
>> +   return -1;
>
> So from here on we always use "orig-head" instead of "head" for
> interactive rebase.
> Would people ever rely on the (internal) file name and have e.g.
> scripts which operate
> on the "head" file ?

This backwards-compatibility code is just a straight port from the
code in git-rebase.sh.

The usage of orig-head has been around since 2011 with 84df456
(rebase: extract code for writing basic state, 2011-02-06), so I guess
if people had issues with it, it would have been reported.

>
>
>> +   strbuf_trim(&sb);
>> +   if (get_oid_hex(sb.buf, &opts->orig_head) < 0)
>> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
>> filename));
>> +
>> +   strbuf_release(&sb);
>> +   return 0;
>> +}
>> +
>> +static int write_state_text(const char *dir, const char *file, const char 
>> *string)
>> +{
>> +   return write_file(mkpath("%s/%s", dir, file), "%s", string);
>> +}
>
> Same comment as on checking the state files existence. I'm not sure if the 
> side
> effect of creating the dir is better done explicitly where it is used.
> The concat of dir and
> file name can still be done in the helper though? (If the helper is
> needed at all then)

Same as above -- AFAIK I don't think mkpath() creates any directories
as a side-effect.

>
>> +
>> +void rebase_options_save(const struct rebase_options *opts, const char *dir)
>> +{
>> +   const char *head_name = opts->orig_refname;
>> +   if (!head_name)
>> +   head_name = "detached HEAD";
>> +   write_state_text(dir, "head-name", head_name);
>> +   write_state_text(dir, "onto", oid_to_hex(&opts->onto));
>> +   write_state_text(dir, "orig-head", oid_to_hex(&opts->orig_head));
>> +}
>> diff --git a/rebase-common.h b

Re: [PATCH/RFC/GSoC 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-19 Thread Johannes Schindelin
Hi Paul,

On Wed, 16 Mar 2016, Paul Tan wrote:

> On Wed, Mar 16, 2016 at 4:04 PM, Johannes Schindelin
>  wrote:
> > In addition I want to point out that sequencer's replay_opts seem to be at
> > least related, but the patch shares none of its code with the sequencer.
> > Let's avoid that.
> >
> > In other words, let's try to add as little code as possible when we can
> > enhance existing code.
> 
> Well, both git-rebase--am.sh and git-rebase--merge.sh do not use the
> sequencer functionality at all, and we don't see git-am for example
> needing to be aware of onto, orig-head, head-name etc.

That is arguing that the implementation of --am and --merge is too far
away from the sequencer and therefore should not be made closer.

By that token, has_unstaged_changes() should never be allowed to call
init_revisions(): it *never* looks at any revisions at all!

And the idea of the sequencer is so much more related to --am and --merge
than unstaged changes are to revisions: the entire purpose of the
sequencer (no matter the *current* implementation with all its
limitations) is to apply a bunch of patches, in sequence. That is pretty
much precisely what *all* members of the rebase family are about.

In other words: please do not let current limitations dictate that we
should introduce diverging code for essentially the same workflow.

Ciao,
Dscho
--
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 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-19 Thread Paul Tan
Hi Dscho,

On Wed, Mar 16, 2016 at 4:04 PM, Johannes Schindelin
 wrote:
> In addition I want to point out that sequencer's replay_opts seem to be at
> least related, but the patch shares none of its code with the sequencer.
> Let's avoid that.
>
> In other words, let's try to add as little code as possible when we can
> enhance existing code.

Well, both git-rebase--am.sh and git-rebase--merge.sh do not use the
sequencer functionality at all, and we don't see git-am for example
needing to be aware of onto, orig-head, head-name etc.

Besides, I don't see why the sequencer needs to be aware of these
rebase-specific options. For simplicity[1], I would think the
sequencer would only need to be aware of what the todo list is, since
that is common to cherry-pick/revert and rebase-i, and all the other
non-sequencer related stuff like checking out the --onto ,
updating refs can be done at the rebase-interactive.c or
git-rebase--interactive.sh layer.

[1] Of course, it's kind of unfortunate that sequencer.c has to be
aware of whether it is being called as cherry-pick or revert, but I
don't see why implementing interactive rebase functionality needs to
make the same mistake.

Thanks,
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 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-16 Thread Johannes Schindelin
Hi Paul,

On Mon, 14 Mar 2016, Stefan Beller wrote:

> On Sat, Mar 12, 2016 at 2:46 AM, Paul Tan  wrote:
> > These functions can be used for loading and saving common rebase options
> > into a state directory.
> >
> > Signed-off-by: Paul Tan 
> > ---
> >  rebase-common.c | 69 
> > +
> >  rebase-common.h |  4 
> >  2 files changed, 73 insertions(+)
> >
> > diff --git a/rebase-common.c b/rebase-common.c
> > index 5a49ac4..1835f08 100644
> > --- a/rebase-common.c
> > +++ b/rebase-common.c
> > @@ -26,3 +26,72 @@ void rebase_options_swap(struct rebase_options *dst, 
> > struct rebase_options *src)
> > *dst = *src;
> > *src = tmp;
> >  }
> > +
> > +static int state_file_exists(const char *dir, const char *file)
> > +{
> > +   return file_exists(mkpath("%s/%s", dir, file));
> > +}
> 
> How is this specific to the state file? All it does is create the
> leading directory
> if it doesn't exist? (So I'd expect file_exists(concat(dir, file)) to
> have the same
> result without actually creating the directory if it doesn't exist as
> a side effect?
> 
> If the dir doesn't exist it can be created in rebase_options_load explicitly?

In addition I want to point out that sequencer's replay_opts seem to be at
least related, but the patch shares none of its code with the sequencer.
Let's avoid that.

In other words, let's try to add as little code as possible when we can
enhance existing code.

Ciao,
Dscho
--
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 05/17] rebase-options: implement rebase_options_load() and rebase_options_save()

2016-03-14 Thread Stefan Beller
On Sat, Mar 12, 2016 at 2:46 AM, Paul Tan  wrote:
> These functions can be used for loading and saving common rebase options
> into a state directory.
>
> Signed-off-by: Paul Tan 
> ---
>  rebase-common.c | 69 
> +
>  rebase-common.h |  4 
>  2 files changed, 73 insertions(+)
>
> diff --git a/rebase-common.c b/rebase-common.c
> index 5a49ac4..1835f08 100644
> --- a/rebase-common.c
> +++ b/rebase-common.c
> @@ -26,3 +26,72 @@ void rebase_options_swap(struct rebase_options *dst, 
> struct rebase_options *src)
> *dst = *src;
> *src = tmp;
>  }
> +
> +static int state_file_exists(const char *dir, const char *file)
> +{
> +   return file_exists(mkpath("%s/%s", dir, file));
> +}

How is this specific to the state file? All it does is create the
leading directory
if it doesn't exist? (So I'd expect file_exists(concat(dir, file)) to
have the same
result without actually creating the directory if it doesn't exist as
a side effect?

If the dir doesn't exist it can be created in rebase_options_load explicitly?


> +
> +static int read_state_file(struct strbuf *sb, const char *dir, const char 
> *file)
> +{
> +   const char *path = mkpath("%s/%s", dir, file);
> +   strbuf_reset(sb);
> +   if (strbuf_read_file(sb, path, 0) >= 0)
> +   return sb->len;
> +   else
> +   return error(_("could not read '%s'"), path);
> +}
> +
> +int rebase_options_load(struct rebase_options *opts, const char *dir)
> +{
> +   struct strbuf sb = STRBUF_INIT;
> +   const char *filename;
> +
> +   /* opts->orig_refname */
> +   if (read_state_file(&sb, dir, "head-name") < 0)
> +   return -1;
> +   strbuf_trim(&sb);
> +   if (starts_with(sb.buf, "refs/heads/"))
> +   opts->orig_refname = strbuf_detach(&sb, NULL);
> +   else if (!strcmp(sb.buf, "detached HEAD"))
> +   opts->orig_refname = NULL;
> +   else
> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
> "head-name"));
> +
> +   /* opts->onto */
> +   if (read_state_file(&sb, dir, "onto") < 0)
> +   return -1;
> +   strbuf_trim(&sb);
> +   if (get_oid_hex(sb.buf, &opts->onto) < 0)
> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
> "onto"));
> +
> +   /*
> +* We always write to orig-head, but interactive rebase used to write
> +* to head. Fall back to reading from head to cover for the case that
> +* the user upgraded git with an ongoing interactive rebase.
> +*/
> +   filename = state_file_exists(dir, "orig-head") ? "orig-head" : "head";
> +   if (read_state_file(&sb, dir, filename) < 0)
> +   return -1;

So from here on we always use "orig-head" instead of "head" for
interactive rebase.
Would people ever rely on the (internal) file name and have e.g.
scripts which operate
on the "head" file ?


> +   strbuf_trim(&sb);
> +   if (get_oid_hex(sb.buf, &opts->orig_head) < 0)
> +   return error(_("could not parse %s"), mkpath("%s/%s", dir, 
> filename));
> +
> +   strbuf_release(&sb);
> +   return 0;
> +}
> +
> +static int write_state_text(const char *dir, const char *file, const char 
> *string)
> +{
> +   return write_file(mkpath("%s/%s", dir, file), "%s", string);
> +}

Same comment as on checking the state files existence. I'm not sure if the side
effect of creating the dir is better done explicitly where it is used.
The concat of dir and
file name can still be done in the helper though? (If the helper is
needed at all then)

> +
> +void rebase_options_save(const struct rebase_options *opts, const char *dir)
> +{
> +   const char *head_name = opts->orig_refname;
> +   if (!head_name)
> +   head_name = "detached HEAD";
> +   write_state_text(dir, "head-name", head_name);
> +   write_state_text(dir, "onto", oid_to_hex(&opts->onto));
> +   write_state_text(dir, "orig-head", oid_to_hex(&opts->orig_head));
> +}
> diff --git a/rebase-common.h b/rebase-common.h
> index db5146a..051c056 100644
> --- a/rebase-common.h
> +++ b/rebase-common.h
> @@ -20,4 +20,8 @@ void rebase_options_release(struct rebase_options *);
>
>  void rebase_options_swap(struct rebase_options *dst, struct rebase_options 
> *src);
>
> +int rebase_options_load(struct rebase_options *, const char *dir);
> +
> +void rebase_options_save(const struct rebase_options *, const char *dir);
> +
>  #endif /* REBASE_COMMON_H */
> --
> 2.7.0
>
--
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