git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "René Scharfe" <rene.scharfe@lsrfire.ath.cx>
To: Dylan Reid <dgreid@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] blame: can specify shas of commits to ignore on command line
Date: Tue, 04 May 2010 23:28:44 +0200	[thread overview]
Message-ID: <4BE0918C.9090204@lsrfire.ath.cx> (raw)
In-Reply-To: <1272939687-17686-1-git-send-email-dgreid@gmail.com>

Am 04.05.2010 04:21, schrieb Dylan Reid:
> Add the ability for git-blame to ignore changes that occur in
> certain commits.  The new "-I <sha>" argument can be used to specify
> a commit that should be ignored.  This is useful if you have a
> few commits that you know didn't cause a problem, for example you
> switched from "u8" to "uint8_t" and it messed up your history.

Only the long option --ignore-commit works with your patch, -I doesn't.

>    Allow multiple commits to be specified and store an array in the
> scoreboard structure so it is accessible.  Add should_ignore_commit
> function to check if a commit should be ignored. Call
> "should_ignore_commit" from blame_overlap and if the commit should
> be ignored then pass all the blame on to the parent of the ignored
> commit.  This is done by calling "pass_whole_blame" which has been
> relocated to a above blame_overlap, but is unchanged.
> 
> Signed-off-by: Dylan Reid <dgreid@gmail.com>
> ---
>  Documentation/blame-options.txt |    6 ++
>  builtin/blame.c                 |  124 +++++++++++++++++++++++++++++----------
>  t/t8003-blame.sh                |   42 +++++++++++++
>  3 files changed, 141 insertions(+), 31 deletions(-)

Oh, nice!  And with tests and documentation! :)

> diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt
> index d820569..eb9c825 100644
> --- a/Documentation/blame-options.txt
> +++ b/Documentation/blame-options.txt
> @@ -52,6 +52,12 @@ of lines before or after the line given by <start>.
>  --porcelain::
>  	Show in a format designed for machine consumption.
>  
> +--ignore-commit <sha>::
> +	Ignore the specified commit when assigning blame.  This is
> +	useful if there are commits in the history that make non
> +	functional changes to the lines you are interested in
> +	finding blame for.
> +
>  --incremental::
>  	Show the result incrementally in a format designed for
>  	machine consumption.
> diff --git a/builtin/blame.c b/builtin/blame.c
> index fc15863..e4bd095 100644
> --- a/builtin/blame.c
> +++ b/builtin/blame.c
> @@ -176,6 +176,14 @@ struct blame_entry {
>  };
>  
>  /*
> + * List of any commits to ignore
> + */
> +struct ignore_commits {
> +	unsigned char (*ignore_shas)[20];
> +	unsigned num_ignore_shas;
> +};
> +
> +/*
>   * The current state of the blame assignment.
>   */
>  struct scoreboard {
> @@ -198,6 +206,9 @@ struct scoreboard {
>  	/* look-up a line in the final buffer */
>  	int num_lines;
>  	int *lineno;
> +
> +	/* List of the shas of commits that should be ignored */
> +	struct ignore_commits *ignored_commits;
>  };
>  
>  static inline int same_suspect(struct origin *a, struct origin *b)
> @@ -653,6 +664,44 @@ static void decref_split(struct blame_entry *split)
>  }
>  
>  /*
> + * The blobs of origin and porigin exactly match, so everything
> + * origin is suspected for can be blamed on the parent.
> + */
> +static void pass_whole_blame(struct scoreboard *sb,
> +			     struct origin *origin, struct origin *porigin)
> +{
> +   struct blame_entry *e;
> +
> +   if (!porigin->file.ptr && origin->file.ptr) {
> +      /* Steal its file */
> +      porigin->file = origin->file;
> +      origin->file.ptr = NULL;
> +   }
> +   for (e = sb->ent; e; e = e->next) {
> +      if (!same_suspect(e->suspect, origin))
> +	 continue;
> +      origin_incref(porigin);
> +      origin_decref(e->suspect);
> +      e->suspect = porigin;
> +   }
> +}

This function was moved from below, but it seems to be indented with
three spaces instead of tabs now.  Adding a declaration without moving
the function would avoid that and result in a smaller patch.

> +
> +/*
> + * Helper to determine if the given commit should be ignored
> + */
> +static unsigned should_ignore_commit(const struct scoreboard *sb,
> +				     struct commit *commit)
> +{
> +	unsigned i;
> +	unsigned num_shas = sb->ignored_commits->num_ignore_shas;
> +	for(i = 0; i < num_shas; i++)
> +		if(!hashcmp(commit->object.sha1,
> +			    sb->ignored_commits->ignore_shas[i]))
> +			return 1;
> +	return 0;
> +}
> +
> +/*
>   * Helper for blame_chunk().  blame_entry e is known to overlap with
>   * the patch hunk; split it and pass blame to the parent.
>   */
> @@ -660,12 +709,15 @@ static void blame_overlap(struct scoreboard *sb, struct blame_entry *e,
>  			  int tlno, int plno, int same,
>  			  struct origin *parent)
>  {
> -	struct blame_entry split[3];
> -
> -	split_overlap(split, e, tlno, plno, same, parent);
> -	if (split[1].suspect)
> -		split_blame(sb, split, e);
> -	decref_split(split);
> +	if(should_ignore_commit(sb, e->suspect->commit))
> +		pass_whole_blame(sb, e->suspect, parent);
> +	else {
> +		struct blame_entry split[3];
> +		split_overlap(split, e, tlno, plno, same, parent);
> +		if (split[1].suspect)
> +			split_blame(sb, split, e);
> +		decref_split(split);
> +	}
>  }
>  
>  /*
> @@ -1105,29 +1157,6 @@ static int find_copy_in_parent(struct scoreboard *sb,
>  }
>  
>  /*
> - * The blobs of origin and porigin exactly match, so everything
> - * origin is suspected for can be blamed on the parent.
> - */
> -static void pass_whole_blame(struct scoreboard *sb,
> -			     struct origin *origin, struct origin *porigin)
> -{
> -	struct blame_entry *e;
> -
> -	if (!porigin->file.ptr && origin->file.ptr) {
> -		/* Steal its file */
> -		porigin->file = origin->file;
> -		origin->file.ptr = NULL;
> -	}
> -	for (e = sb->ent; e; e = e->next) {
> -		if (!same_suspect(e->suspect, origin))
> -			continue;
> -		origin_incref(porigin);
> -		origin_decref(e->suspect);
> -		e->suspect = porigin;
> -	}
> -}
> -
> -/*
>   * We pass blame from the current commit to its parents.  We keep saying
>   * "parent" (and "porigin"), but what we mean is to find scapegoat to
>   * exonerate ourselves.
> @@ -1540,8 +1569,14 @@ static void assign_blame(struct scoreboard *sb, int opt)
>  
>  		/* Take responsibility for the remaining entries */
>  		for (ent = sb->ent; ent; ent = ent->next)
> -			if (same_suspect(ent->suspect, suspect))
> -				found_guilty_entry(ent);
> +			if (same_suspect(ent->suspect, suspect)) {
> +				if (should_ignore_commit(sb, commit) &&
> +				    ent->suspect->previous)
> +					pass_whole_blame(sb, ent->suspect,
> +							 ent->suspect->previous);
> +				else
> +					found_guilty_entry(ent);
> +		   }

An ignored commit can still be blamed if there is no other commit to
pass it on.  So e.g. the initial commit for the file could end up being
blamed for lines that were added by later commits which are being
ignored.  That may look confusing.

Would it make sense to pass the blame to some kind of null commit, i.e.
a special marker that says "I could tell you who is to blame for this
line but you said you don't want to know"?

René

  reply	other threads:[~2010-05-04 21:29 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-04  2:21 [PATCH] blame: can specify shas of commits to ignore on command line Dylan Reid
2010-05-04 21:28 ` René Scharfe [this message]
2010-05-04 21:46   ` Dylan Reid
2010-05-04 23:01     ` Junio C Hamano
2010-05-04 23:08       ` Dylan Reid
2010-05-05  5:19         ` Junio C Hamano
2010-05-05  5:28           ` Dylan Reid
2012-03-08 21:01             ` cnighswonger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4BE0918C.9090204@lsrfire.ath.cx \
    --to=rene.scharfe@lsrfire.ath.cx \
    --cc=dgreid@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).