blame: add --ignore-revs-blob and blame.ignoreRevsBlob
PATCH 1/1 blame: add --ignore-revs-blob and blame.ignoreRevsBlob
From: David Barr <[email protected]>
In a bare repository, there isn't a simple way to ignore revisions via a file without extracting it to a temporary file.
This patch provides a command-line option and config variable, similar to --ignore-revs-file and blame.ignoreRevsFile, which reads the list of revisions to ignore from a blob in the repository.
---
blame: Add --ignore-revs-blob and blame.ignoreRevsBlob
In a bare repository, there isn't a simple way to ignore revisions via a file without extracting it to a temporary file.
This patch provides a command-line option and config variable, similar to --ignore-revs-file and blame.ignoreRevsFile, which reads the list of revisions to ignore from a blob in the repository.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1204%2Fdavebarrau%2Fadd-ignore-revs-blob-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1204/davebarrau/add-ignore-revs-blob-v1
Pull-Request: https://github.com/git/git/pull/1204
Documentation/blame-options.txt | 10 ++-- Documentation/config/blame.txt | 7 ++- builtin/blame.c | 23 ++++++++- oidset.c | 84 ++++++++++++++++++++++++++------- oidset.h | 2 + t/t8013-blame-ignore-revs.sh | 19 ++++++++ 6 files changed, 124 insertions(+), 21 deletions(-)
Documentation/blame-options.txt +7 -3
@@ -132,9 +132,13 @@ take effect. --ignore-revs-file <file>:: Ignore revisions listed in `file`, which must be in the same format as an `fsck.skipList`. This option may be repeated, and these files will be - processed after any files specified with the `blame.ignoreRevsFile` config - option. An empty file name, `""`, will clear the list of revs from - previously processed files. + processed after any files specified with the `blame.ignoreRevsFile` or + `blame.ignoreRevsBlob` config options. An empty file name, `""`, will + clear the list of revs from previously processed files. + +--ignore-revs-blob <blob>:: + Like `--ignore-revs-file`, but consider the value as a reference to a blob + in the repository. --color-lines:: Color line annotations in the default format differently if they come from
Documentation/config/blame.txt +6 -1
@@ -25,7 +25,12 @@ blame.ignoreRevsFile:: line, in linkgit:git-blame[1]. Whitespace and comments beginning with `#` are ignored. This option may be repeated multiple times. Empty file names will reset the list of ignored revisions. This option will - be handled before the command line option `--ignore-revs-file`. + be handled before the command line options `--ignore-revs-file` and + `--ignore-revs-blob`. + +blame.ignoreRevsBlob:: + Like `blame.ignoreRevsFile`, but consider the value as a reference to + a blob in the repository. blame.markUnblamableLines:: Mark lines that were changed by an ignored revision that we could not
builtin/blame.c +22 -1
@@ -54,6 +54,7 @@ static int show_progress;static char repeated_meta_color[COLOR_MAXLEN ];static int coloring_mode;static struct string_list ignore_revs_file_list =STRING_LIST_INIT_NODUP ; +static struct string_list ignore_revs_blob_list =STRING_LIST_INIT_NODUP ;static int mark_unblamable_lines;static int mark_ignored_lines;
@@ -711,6 +712,16 @@ static int git_blame_config(const char *var, const char *value, void *cb)string_list_insert (&ignore_revs_file_list, str);return 0 ; } +if (!strcmp (var,"blame.ignorerevsblob" )) { +const char *str; +int ret; + + ret =git_config_string (&str, var, value); +if (ret) +return ret; +string_list_insert (&ignore_revs_blob_list, str); +return 0 ; + }if (!strcmp (var,"blame.markunblamablelines" )) { mark_unblamable_lines =git_config_bool (var, value);return 0 ;
@@ -822,6 +833,7 @@ static int peel_to_commit_oid(struct object_id *oid_ret, void *cbdata)static void build_ignorelist (struct blame_scoreboard *sb,struct string_list *ignore_revs_file_list, +struct string_list *ignore_revs_blob_list,struct string_list *ignore_rev_list) {struct string_list_item *i;
@@ -835,6 +847,13 @@ static void build_ignorelist(struct blame_scoreboard *sb,oidset_parse_file_carefully (&sb->ignore_list, i->string, peel_to_commit_oid, sb); } +for_each_string_list_item (i, ignore_revs_blob_list) { +if (!strcmp (i->string,"" )) +oidset_clear (&sb->ignore_list); +else +oidset_parse_blob (&sb->ignore_list, i->string, + peel_to_commit_oid, sb); + }for_each_string_list_item (i, ignore_rev_list) {if (get_oid_committish (i->string, &oid) ||peel_to_commit_oid (&oid, sb))
@@ -878,6 +897,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)OPT_BIT ('w' ,NULL , &xdl_opts,N_ ("ignore whitespace differences" ),XDF_IGNORE_WHITESPACE ),OPT_STRING_LIST (0 ,"ignore-rev" , &ignore_rev_list,N_ ("rev" ),N_ ("ignore <rev> when blaming" )),OPT_STRING_LIST (0 ,"ignore-revs-file" , &ignore_revs_file_list,N_ ("file" ),N_ ("ignore revisions from <file>" )), +OPT_STRING_LIST (0 ,"ignore-revs-blob" , &ignore_revs_blob_list,N_ ("blob" ),N_ ("ignore revisions from <blob>" )),OPT_BIT (0 ,"color-lines" , &output_option,N_ ("color redundant metadata from previous line differently" ),OUTPUT_COLOR_LINE ),OPT_BIT (0 ,"color-by-age" , &output_option,N_ ("color lines by age" ),OUTPUT_SHOW_AGE_WITH_COLOR ), OPT_BIT(0, "minimal", &xdl_opts, N_("spend extra cycles to find better match"), XDF_NEED_MINIMAL),
@@ -1084,8 +1104,9 @@ parse_done: sb.reverse = reverse; sb.repo = the_repository; sb.path = path; -build_ignorelist (&sb, &ignore_revs_file_list, &ignore_rev_list); +build_ignorelist (&sb, &ignore_revs_file_list, &ignore_revs_blob_list, &ignore_rev_list);string_list_clear (&ignore_revs_file_list,0 ); +string_list_clear (&ignore_revs_blob_list,0 );string_list_clear (&ignore_rev_list,0 );setup_scoreboard (&sb, &o);
oidset.c +68 -16
105 lines not on this page · raw message
oidset.h +2 -0
@@ -84,6 +84,8 @@ void oidset_parse_file(struct oidset *set, const char *path);typedef int (*oidset_parse_tweak_fn )(struct object_id *,void *);void oidset_parse_file_carefully (struct oidset *set,const char *path,oidset_parse_tweak_fn fn,void *cbdata); +void oidset_parse_blob (struct oidset *set,const char *path, +oidset_parse_tweak_fn fn,void *cbdata);struct oidset_iter {kh_oid_set_t *set;
t/t8013-blame-ignore-revs.sh +19 -0
@@ -115,6 +115,25 @@ test_expect_success ignore_revs_from_configs_and_files ' test_cmp expect actual ' +# Ignore X from the config option, Y from a file. +test_expect_success ignore_revs_from_configs_and_blobs ' + git rev-parse X >ignore_x && + git rev-parse Y >ignore_y && + git add ignore_x ignore_y && + git commit -m ignore && + git config --add blame.ignoreRevsBlob HEAD:ignore_x && + git blame --line-porcelain file --ignore-revs-blob HEAD:ignore_y >blame_raw 2>&1 && + git config --unset blame.ignoreRevsBlob HEAD:ignore_x && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse A >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse B >expect && + test_cmp expect actual +' + # Override blame.ignoreRevsFile (ignore_x) with an empty string. X should be # blamed now for lines 1 and 2, since we are no longer ignoring X. test_expect_success override_ignore_revs_file '
base-commit: 297ca895a27a6bbdb7906371d533f72a12ad25b2
Signature · 1 line
gitgitgadget
Quoted 6 lines · David Barr via GitGitGadget
From: David Barr <[email protected]>
In a bare repository, there isn't a simple way to ignore revisions via a file without extracting it to a temporary file.
Quoted 8 lines
This patch provides a command-line option and config variable, similar to --ignore-revs-file and blame.ignoreRevsFile, which reads the list of revisions to ignore from a blob in the repository.
Signed-off-by David Barr <[email protected]>---
Looks like this patch might have gotten lost in the noise.
Could anyone take a look?
Quoted 288 lines
blame: Add --ignore-revs-blob and blame.ignoreRevsBlob
In a bare repository, there isn't a simple way to ignore revisions via a file without extracting it to a temporary file.
This patch provides a command-line option and config variable, similar to --ignore-revs-file and blame.ignoreRevsFile, which reads the list of revisions to ignore from a blob in the repository.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1204%2Fdavebarrau%2Fadd-ignore-revs-blob-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1204/davebarrau/add-ignore-revs-blob-v1
Pull-Request: https://github.com/git/git/pull/1204Documentation/blame-options.txt | 10 ++-- Documentation/config/blame.txt | 7 ++- builtin/blame.c | 23 ++++++++- oidset.c | 84 ++++++++++++++++++++++++++------- oidset.h | 2 + t/t8013-blame-ignore-revs.sh | 19 ++++++++ 6 files changed, 124 insertions(+), 21 deletions(-)Documentation/blame-options.txt +7
-3@@ -132,9 +132,13 @@ take effect. --ignore-revs-file <file>:: Ignore revisions listed in `file`, which must be in the same format as an `fsck.skipList`. This option may be repeated, and these files will be - processed after any files specified with the `blame.ignoreRevsFile` config - option. An empty file name, `""`, will clear the list of revs from - previously processed files. + processed after any files specified with the `blame.ignoreRevsFile` or + `blame.ignoreRevsBlob` config options. An empty file name, `""`, will + clear the list of revs from previously processed files. + +--ignore-revs-blob <blob>:: + Like `--ignore-revs-file`, but consider the value as a reference to a blob + in the repository. --color-lines:: Color line annotations in the default format differently if they come fromDocumentation/config/blame.txt +6
-1@@ -25,7 +25,12 @@ blame.ignoreRevsFile:: line, in linkgit:git-blame[1]. Whitespace and comments beginning with `#` are ignored. This option may be repeated multiple times. Empty file names will reset the list of ignored revisions. This option will - be handled before the command line option `--ignore-revs-file`. + be handled before the command line options `--ignore-revs-file` and + `--ignore-revs-blob`. + +blame.ignoreRevsBlob:: + Like `blame.ignoreRevsFile`, but consider the value as a reference to + a blob in the repository. blame.markUnblamableLines:: Mark lines that were changed by an ignored revision that we could notbuiltin/blame.c +22
-1@@ -54,6 +54,7 @@ static int show_progress;static char repeated_meta_color[COLOR_MAXLEN ];static int coloring_mode;static struct string_list ignore_revs_file_list =STRING_LIST_INIT_NODUP ; +static struct string_list ignore_revs_blob_list =STRING_LIST_INIT_NODUP ;static int mark_unblamable_lines;static int mark_ignored_lines;@@ -711,6 +712,16 @@ static int git_blame_config(const char *var, const char *value, void *cb)string_list_insert (&ignore_revs_file_list, str);return 0 ; } +if (!strcmp (var,"blame.ignorerevsblob" )) { +const char *str; +int ret; + + ret =git_config_string (&str, var, value); +if (ret) +return ret; +string_list_insert (&ignore_revs_blob_list, str); +return 0 ; + }if (!strcmp (var,"blame.markunblamablelines" )) { mark_unblamable_lines =git_config_bool (var, value);return 0 ;@@ -822,6 +833,7 @@ static int peel_to_commit_oid(struct object_id *oid_ret, void *cbdata)static void build_ignorelist (struct blame_scoreboard *sb,struct string_list *ignore_revs_file_list, +struct string_list *ignore_revs_blob_list,struct string_list *ignore_rev_list) {struct string_list_item *i;@@ -835,6 +847,13 @@ static void build_ignorelist(struct blame_scoreboard *sb,oidset_parse_file_carefully (&sb->ignore_list, i->string, peel_to_commit_oid, sb); } +for_each_string_list_item (i, ignore_revs_blob_list) { +if (!strcmp (i->string,"" )) +oidset_clear (&sb->ignore_list); +else +oidset_parse_blob (&sb->ignore_list, i->string, + peel_to_commit_oid, sb); + }for_each_string_list_item (i, ignore_rev_list) {if (get_oid_committish (i->string, &oid) ||peel_to_commit_oid (&oid, sb))@@ -878,6 +897,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)OPT_BIT ('w' ,NULL , &xdl_opts,N_ ("ignore whitespace differences" ),XDF_IGNORE_WHITESPACE ),OPT_STRING_LIST (0 ,"ignore-rev" , &ignore_rev_list,N_ ("rev" ),N_ ("ignore <rev> when blaming" )),OPT_STRING_LIST (0 ,"ignore-revs-file" , &ignore_revs_file_list,N_ ("file" ),N_ ("ignore revisions from <file>" )), +OPT_STRING_LIST (0 ,"ignore-revs-blob" , &ignore_revs_blob_list,N_ ("blob" ),N_ ("ignore revisions from <blob>" )),OPT_BIT (0 ,"color-lines" , &output_option,N_ ("color redundant metadata from previous line differently" ),OUTPUT_COLOR_LINE ),OPT_BIT (0 ,"color-by-age" , &output_option,N_ ("color lines by age" ),OUTPUT_SHOW_AGE_WITH_COLOR ), OPT_BIT(0, "minimal", &xdl_opts, N_("spend extra cycles to find better match"), XDF_NEED_MINIMAL),@@ -1084,8 +1104,9 @@ parse_done: sb.reverse = reverse; sb.repo = the_repository; sb.path = path; -build_ignorelist (&sb, &ignore_revs_file_list, &ignore_rev_list); +build_ignorelist (&sb, &ignore_revs_file_list, &ignore_revs_blob_list, &ignore_rev_list);string_list_clear (&ignore_revs_file_list,0 ); +string_list_clear (&ignore_revs_blob_list,0 );string_list_clear (&ignore_rev_list,0 );setup_scoreboard (&sb, &o);oidset.c +68
-16@@ -1,5 +1,6 @@#include "cache.h" #include "oidset.h" +#include "object-store.h" void oidset_init (struct oidset *set,size_t initial_size) {@@ -41,6 +42,29 @@ void oidset_parse_file(struct oidset *set, const char *path)oidset_parse_file_carefully (set, path,NULL ,NULL ); } +static int read_oidset_line (struct strbuf sb,struct object_id *oid) +{ +const char *p; +const char *name; + +/* +* Allow trailing comments, leading whitespace +* (including before commits), and empty or whitespace +* only lines. +*/ + name =strchr (sb.buf,'#' ); +if (name) +strbuf_setlen (&sb, name - sb.buf); +strbuf_trim (&sb); +if (!sb.len) +return 0 ; + +if (parse_oid_hex (sb.buf, oid, &p) || *p !='\0' ) +die ("invalid object name: %s" , sb.buf); + +return 1 ; +} +void oidset_parse_file_carefully (struct oidset *set,const char *path,oidset_parse_tweak_fn fn,void *cbdata) {@@ -52,23 +76,8 @@ void oidset_parse_file_carefully(struct oidset *set, const char *path,if (!fp)die ("could not open object name list: %s" , path);while (!strbuf_getline (&sb, fp)) { -const char *p; -const char *name; - -/* -* Allow trailing comments, leading whitespace -* (including before commits), and empty or whitespace -* only lines. -*/ - name =strchr (sb.buf,'#' ); -if (name) -strbuf_setlen (&sb, name - sb.buf); -strbuf_trim (&sb); -if (!sb.len) +if (!read_oidset_line (sb, &oid))continue ; - -if (parse_oid_hex (sb.buf, &oid, &p) || *p !='\0' ) -die ("invalid object name: %s" , sb.buf);if (fn &&fn (&oid, cbdata))continue ;oidset_insert (set, &oid);@@ -78,3 +87,46 @@ void oidset_parse_file_carefully(struct oidset *set, const char *path,fclose (fp);strbuf_release (&sb); } + +static void read_oidset_string (struct oidset *set,oidset_parse_tweak_fn fn, +void *cbdata,const char *buf,unsigned long size) +{ +struct object_id oid; +struct strbuf **lines; +struct strbuf **line; + + lines =strbuf_split_buf (buf, size,'\n' ,0 ); + +for (line = lines; *line; line++) { +if (!read_oidset_line (**line, &oid)) +continue ; +if (fn &&fn (&oid, cbdata)) +continue ; +oidset_insert (set, &oid); + } +strbuf_list_free (lines); +} + +void oidset_parse_blob (struct oidset *set,const char *name, +oidset_parse_tweak_fn fn,void *cbdata) +{ +struct object_id oid; +char *buf; +unsigned long size; +enum object_type type; + +if (!name) { +return ; + } +if (get_oid (name, &oid) <0 ) { +die ("unable to read object id for %s" , name); + } + buf =read_object_file (&oid, &type, &size); +if (!buf) +die ("unable to read oidset file at %s" , name); +if (type !=OBJ_BLOB ) +die ("oidset file is not a blob: %s" , name); + +read_oidset_string (set, fn, cbdata, buf, size); +free (buf); +}oidset.h +2
-0@@ -84,6 +84,8 @@ void oidset_parse_file(struct oidset *set, const char *path);typedef int (*oidset_parse_tweak_fn )(struct object_id *,void *);void oidset_parse_file_carefully (struct oidset *set,const char *path,oidset_parse_tweak_fn fn,void *cbdata); +void oidset_parse_blob (struct oidset *set,const char *path, +oidset_parse_tweak_fn fn,void *cbdata);struct oidset_iter {kh_oid_set_t *set;t/t8013-blame-ignore-revs.sh +19
-0@@ -115,6 +115,25 @@ test_expect_success ignore_revs_from_configs_and_files ' test_cmp expect actual ' +# Ignore X from the config option, Y from a file. +test_expect_success ignore_revs_from_configs_and_blobs ' + git rev-parse X >ignore_x && + git rev-parse Y >ignore_y && + git add ignore_x ignore_y && + git commit -m ignore && + git config --add blame.ignoreRevsBlob HEAD:ignore_x && + git blame --line-porcelain file --ignore-revs-blob HEAD:ignore_y >blame_raw 2>&1 && + git config --unset blame.ignoreRevsBlob HEAD:ignore_x && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse A >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse B >expect && + test_cmp expect actual +' + # Override blame.ignoreRevsFile (ignore_x) with an empty string. X should be # blamed now for lines 1 and 2, since we are no longer ignoring X. test_expect_success override_ignore_revs_file 'base-commit:
297ca895a27a6bbdb7906371d533f72a12ad25b2