{"thread":{"id":"47031","subject":"[PATCH] blame: add --fuzzy-lines command line option","startedAt":"2017-10-26T02:19:50Z","lastAt":"2018-05-31T05:08:06Z","messageCount":27,"participants":["Isabella Stephens","Junio C Hamano","Jacob Keller","SZEDER Gábor","Eric Sunshine","istephens@atlassian.com"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"331060","messageId":"20171026021929.1346-1-istephens@atlassian.com","threadId":"47031","inReplyTo":null,"subject":"[PATCH] blame: add --fuzzy-lines command line option","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-26T02:19:29Z","receivedAt":"2017-10-26T02:19:50Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"If the -L option is used to specify a line range in git blame, and the\nend of the range is past the end of the file, git will fail with a fatal\nerror. It may instead be desirable to perform a git blame for the line\nnumbers in the intersection of the file and the specified line range.\nThis patch adds a --fuzzy-lines command line option to allow this.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n Documentation/blame-options.txt | 5 +++++\n builtin/blame.c                 | 4 ++++\n t/t8003-blame-corner-cases.sh   | 6 ++++++\n 3 files changed, 15 insertions(+)\n\ndiff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt\nindex dc41957af..664cd8f8b 100644\n--- a/Documentation/blame-options.txt\n+++ b/Documentation/blame-options.txt\n@@ -19,6 +19,11 @@\n +\n include::line-range-format.txt[]\n \n+--fuzzy-lines::\n+\tUse fuzzy line ranges. If a range specified with -L starts on a line\n+\twithin the file but ends past the end of the file, display the blame\n+\tfor the existing lines rather than failing.\n+\n -l::\n \tShow long rev (Default: off).\n \ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 67adaef4d..d25b39d40 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -661,6 +661,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \n \tstruct string_list range_list = STRING_LIST_INIT_NODUP;\n \tint output_option = 0, opt = 0;\n+\tint fuzzy_lines = 0;\n \tint show_stats = 0;\n \tconst char *revs_file = NULL;\n \tconst char *contents_from = NULL;\n@@ -670,6 +671,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"root\", &show_root, N_(\"Do not treat root commits as boundaries (Default: off)\")),\n \t\tOPT_BOOL(0, \"show-stats\", &show_stats, N_(\"Show work cost statistics\")),\n \t\tOPT_BOOL(0, \"progress\", &show_progress, N_(\"Force progress reporting\")),\n+\t\tOPT_BOOL(0, \"fuzzy-lines\", &fuzzy_lines, N_(\"Use fuzzy line ranges\")),\n \t\tOPT_BIT(0, \"score-debug\", &output_option, N_(\"Show output score for blame entries\"), OUTPUT_SHOW_SCORE),\n \t\tOPT_BIT('f', \"show-name\", &output_option, N_(\"Show original filename (Default: auto)\"), OUTPUT_SHOW_NAME),\n \t\tOPT_BIT('n', \"show-number\", &output_option, N_(\"Show original linenumber (Default: off)\"), OUTPUT_SHOW_NUMBER),\n@@ -878,6 +880,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n \t\t\t\t    &bottom, &top, sb.path))\n \t\t\tusage(blame_usage);\n+\t\tif (fuzzy_lines && lno < top)\n+\t\t\ttop = lno;\n \t\tif (lno < top || ((lno || bottom) && lno < bottom))\n \t\t\tdie(Q_(\"file %s has only %lu line\",\n \t\t\t       \"file %s has only %lu lines\",\ndiff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\nindex 661f9d430..6e7657df2 100755\n--- a/t/t8003-blame-corner-cases.sh\n+++ b/t/t8003-blame-corner-cases.sh\n@@ -220,6 +220,12 @@ test_expect_success 'blame -L with invalid end' '\n \ttest_i18ngrep \"has only 2 lines\" errors\n '\n \n+test_expect_success 'blame -L with invalid end and fuzzy-lines' '\n+\tgit blame -L1,5 tres --fuzzy-lines >out &&\n+\tcat out &&\n+\ttest $(wc -l < out) -eq 2\n+'\n+\n test_expect_success 'blame parses <end> part of -L' '\n \tgit blame -L1,1 tres >out &&\n \tcat out &&\n-- \n2.14.1\n\n"},{"id":"331067","messageId":"xmqqtvyme8pg.fsf@gitster.mtv.corp.google.com","threadId":"47031","inReplyTo":"20171026021929.1346-1-istephens@atlassian.com","subject":"Re: [PATCH] blame: add --fuzzy-lines command line option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-10-26T06:15:07Z","receivedAt":"2017-10-26T06:15:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Isabella Stephens <istephens@atlassian.com> writes:\n\n> If the -L option is used to specify a line range in git blame, and the\n> end of the range is past the end of the file, git will fail with a fatal\n> error. It may instead be desirable to perform a git blame for the line\n> numbers in the intersection of the file and the specified line range.\n\nEven though erroring out upon such input was done as a deliberate\ndesign decision, in retrospect, I do not think the design decision\nmade much sense.\n\nThe code already takes a nonsense input and tries to make best sense\nof it, e.g. \"-L10,6\" is interpreted as \"-L6,10\" instead of erroring\nout.  So if we were to do this kind of change, I suspect that it may\nbe better to do so unconditionally without introducing a new option.\n\nThanks.\n"},{"id":"331070","messageId":"20171026070108.4185-1-istephens@atlassian.com","threadId":"47031","inReplyTo":"xmqqtvyme8pg.fsf@gitster.mtv.corp.google.com","subject":"[PATCH v2] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-26T07:01:08Z","receivedAt":"2017-10-26T07:01:28Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"If the -L option is used to specify a line range in git blame, and the\nend of the range is past the end of the file, at present git will fail\nwith a fatal error. This commit prevents such behaviour - instead the\nblame is display for any existing lines within the specified range.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n builtin/blame.c               | 4 ++--\n t/t8003-blame-corner-cases.sh | 5 +++--\n 2 files changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 67adaef4d..b5b9db147 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n \t\t\t\t    &bottom, &top, sb.path))\n \t\t\tusage(blame_usage);\n-\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n+\t\tif ((lno || bottom) && lno < bottom)\n \t\t\tdie(Q_(\"file %s has only %lu line\",\n \t\t\t       \"file %s has only %lu lines\",\n \t\t\t       lno), path, lno);\n \t\tif (bottom < 1)\n \t\t\tbottom = 1;\n-\t\tif (top < 1)\n+\t\tif (top < 1 || lno < top)\n \t\t\ttop = lno;\n \t\tbottom--;\n \t\trange_set_append_unsafe(&ranges, bottom, top);\ndiff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\nindex 661f9d430..32b3788fe 100755\n--- a/t/t8003-blame-corner-cases.sh\n+++ b/t/t8003-blame-corner-cases.sh\n@@ -216,8 +216,9 @@ test_expect_success 'blame -L with invalid start' '\n '\n \n test_expect_success 'blame -L with invalid end' '\n-\ttest_must_fail git blame -L1,5 tres 2>errors &&\n-\ttest_i18ngrep \"has only 2 lines\" errors\n+\tgit blame -L1,5 tres >out &&\n+\tcat out &&\n+\ttest $(wc -l < out) -eq 2\n '\n \n test_expect_success 'blame parses <end> part of -L' '\n-- \n2.14.1\n\n"},{"id":"331071","messageId":"fab198e6-a736-ff2c-1c37-719b07531942@atlassian.com","threadId":"47031","inReplyTo":"xmqqtvyme8pg.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] blame: add --fuzzy-lines command line option","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-26T07:08:12Z","receivedAt":"2017-10-26T07:08:22Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"On 26/10/17 5:15 pm, Junio C Hamano wrote:\n> Isabella Stephens <istephens@atlassian.com> writes:\n> \n>> If the -L option is used to specify a line range in git blame, and the\n>> end of the range is past the end of the file, git will fail with a fatal\n>> error. It may instead be desirable to perform a git blame for the line\n>> numbers in the intersection of the file and the specified line range.\n> \n> Even though erroring out upon such input was done as a deliberate\n> design decision, in retrospect, I do not think the design decision\n> made much sense.\n> \n> The code already takes a nonsense input and tries to make best sense\n> of it, e.g. \"-L10,6\" is interpreted as \"-L6,10\" instead of erroring\n> out.  So if we were to do this kind of change, I suspect that it may\n> be better to do so unconditionally without introducing a new option.\n> \n> Thanks.\n> \n\nThanks for following up. I've sent through a version 2 of the patch \nwithout the command line option.\n"},{"id":"331080","messageId":"CA+P7+xpk+9R9kMGNky4vTRpASf_nXM1xt0KHFjqwn8aB1NzDAQ@mail.gmail.com","threadId":"47031","inReplyTo":"20171026070108.4185-1-istephens@atlassian.com","subject":"Re: [PATCH v2] blame: prevent error if range ends past end of file","fromName":"Jacob Keller","fromEmail":"jacob.keller@gmail.com","sentAt":"2017-10-26T08:48:12Z","receivedAt":"2017-10-26T08:48:40Z","isPatch":true,"sender":{"key":"jacob.keller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"On Thu, Oct 26, 2017 at 12:01 AM, Isabella Stephens\n<istephens@atlassian.com> wrote:\n> If the -L option is used to specify a line range in git blame, and the\n> end of the range is past the end of the file, at present git will fail\n> with a fatal error. This commit prevents such behaviour - instead the\n> blame is display for any existing lines within the specified range.\n>\n> Signed-off-by: Isabella Stephens <istephens@atlassian.com>\n> ---\n\nI like this change. We might want to document L to indicate that an L\nthat is outside the range of lines will show all lines that do match.\n\nMaybe we also want it to only succeed if at least some lines are\nblamed? Could we make it so that it fails if no lines are within the\nrange? (ie: the start point is too far in? or does it already do\nsuch?)\n\nThanks,\nJake\n\n>  builtin/blame.c               | 4 ++--\n>  t/t8003-blame-corner-cases.sh | 5 +++--\n>  2 files changed, 5 insertions(+), 4 deletions(-)\n>\n> diff --git a/builtin/blame.c b/builtin/blame.c\n> index 67adaef4d..b5b9db147 100644\n> --- a/builtin/blame.c\n> +++ b/builtin/blame.c\n> @@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n>                                     nth_line_cb, &sb, lno, anchor,\n>                                     &bottom, &top, sb.path))\n>                         usage(blame_usage);\n> -               if (lno < top || ((lno || bottom) && lno < bottom))\n> +               if ((lno || bottom) && lno < bottom)\n>                         die(Q_(\"file %s has only %lu line\",\n>                                \"file %s has only %lu lines\",\n>                                lno), path, lno);\n>                 if (bottom < 1)\n>                         bottom = 1;\n> -               if (top < 1)\n> +               if (top < 1 || lno < top)\n>                         top = lno;\n>                 bottom--;\n>                 range_set_append_unsafe(&ranges, bottom, top);\n> diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\n> index 661f9d430..32b3788fe 100755\n> --- a/t/t8003-blame-corner-cases.sh\n> +++ b/t/t8003-blame-corner-cases.sh\n> @@ -216,8 +216,9 @@ test_expect_success 'blame -L with invalid start' '\n>  '\n>\n>  test_expect_success 'blame -L with invalid end' '\n> -       test_must_fail git blame -L1,5 tres 2>errors &&\n> -       test_i18ngrep \"has only 2 lines\" errors\n> +       git blame -L1,5 tres >out &&\n> +       cat out &&\n> +       test $(wc -l < out) -eq 2\n>  '\n>\n>  test_expect_success 'blame parses <end> part of -L' '\n> --\n> 2.14.1\n>\n"},{"id":"331090","messageId":"20171026153111.21813-1-szeder.dev@gmail.com","threadId":"47031","inReplyTo":"20171026070108.4185-1-istephens@atlassian.com","subject":"Re: [PATCH v2] blame: prevent error if range ends past end of file","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2017-10-26T15:31:11Z","receivedAt":"2017-10-26T15:31:32Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"> If the -L option is used to specify a line range in git blame, and the\n> end of the range is past the end of the file, at present git will fail\n> with a fatal error. This commit prevents such behaviour - instead the\n> blame is display for any existing lines within the specified range.\n\ns/is display/is displayed/ ?\n\n'git log' has a very similar -L option, which errors out, too, if the\nend of the line range is past the end of the file.  IMHO the\ninterpretation of the line range -L<start>,<end> should be kept\nconsistent in the two commands, and 'git log' shouldn't error out,\neither.\n\n> Signed-off-by: Isabella Stephens <istephens@atlassian.com>\n> ---\n>  builtin/blame.c               | 4 ++--\n>  t/t8003-blame-corner-cases.sh | 5 +++--\n>  2 files changed, 5 insertions(+), 4 deletions(-)\n> \n> diff --git a/builtin/blame.c b/builtin/blame.c\n> index 67adaef4d..b5b9db147 100644\n> --- a/builtin/blame.c\n> +++ b/builtin/blame.c\n> @@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n>  \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n>  \t\t\t\t    &bottom, &top, sb.path))\n>  \t\t\tusage(blame_usage);\n> -\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n> +\t\tif ((lno || bottom) && lno < bottom)\n>  \t\t\tdie(Q_(\"file %s has only %lu line\",\n>  \t\t\t       \"file %s has only %lu lines\",\n>  \t\t\t       lno), path, lno);\n>  \t\tif (bottom < 1)\n>  \t\t\tbottom = 1;\n> -\t\tif (top < 1)\n> +\t\tif (top < 1 || lno < top)\n>  \t\t\ttop = lno;\n>  \t\tbottom--;\n>  \t\trange_set_append_unsafe(&ranges, bottom, top);\n> diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\n> index 661f9d430..32b3788fe 100755\n> --- a/t/t8003-blame-corner-cases.sh\n> +++ b/t/t8003-blame-corner-cases.sh\n> @@ -216,8 +216,9 @@ test_expect_success 'blame -L with invalid start' '\n>  '\n>  \n>  test_expect_success 'blame -L with invalid end' '\n> -\ttest_must_fail git blame -L1,5 tres 2>errors &&\n> -\ttest_i18ngrep \"has only 2 lines\" errors\n> +\tgit blame -L1,5 tres >out &&\n> +\tcat out &&\n> +\ttest $(wc -l < out) -eq 2\n\nPlease use the test_line_count helper instead, as it will output a\nhelpful error message on failure, making the 'cat out' above\nunnecessary.\n\n>  '\n>  \n>  test_expect_success 'blame parses <end> part of -L' '\n> -- \n> 2.14.1\n> \n> \n"},{"id":"331126","messageId":"f22b2cda-745b-ee00-2578-cf5cec13d050@atlassian.com","threadId":"47031","inReplyTo":"CA+P7+xpk+9R9kMGNky4vTRpASf_nXM1xt0KHFjqwn8aB1NzDAQ@mail.gmail.com","subject":"Re: [PATCH v2] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-26T22:50:26Z","receivedAt":"2017-10-26T22:50:36Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"On 26/10/17 7:48 pm, Jacob Keller wrote:\n> On Thu, Oct 26, 2017 at 12:01 AM, Isabella Stephens\n> <istephens@atlassian.com> wrote:\n>> If the -L option is used to specify a line range in git blame, and the\n>> end of the range is past the end of the file, at present git will fail\n>> with a fatal error. This commit prevents such behaviour - instead the\n>> blame is display for any existing lines within the specified range.\n>>\n>> Signed-off-by: Isabella Stephens <istephens@atlassian.com>\n>> ---\n> \n> I like this change. We might want to document L to indicate that an L\n> that is outside the range of lines will show all lines that do match.\n> \n> Maybe we also want it to only succeed if at least some lines are\n> blamed? Could we make it so that it fails if no lines are within the\n> range? (ie: the start point is too far in? or does it already do\n> such?)\n> \n> Thanks,\n> Jake\n\nYep, that is exactly how it behaves now - if a range intersects the\nfile at all it will annotate the relevant lines, otherwise it will fail.\n\nI'll add a clarification to the documentation in my next revision.\nThanks for reviewing!\n"},{"id":"331127","messageId":"acc03a7d-69a6-680a-a435-dbdc50cf1e87@atlassian.com","threadId":"47031","inReplyTo":"20171026153111.21813-1-szeder.dev@gmail.com","subject":"Re: [PATCH v2] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-26T23:37:25Z","receivedAt":"2017-10-26T23:37:34Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"On 27/10/17 2:31 am, SZEDER Gábor wrote:\n>> If the -L option is used to specify a line range in git blame, and the\n>> end of the range is past the end of the file, at present git will fail\n>> with a fatal error. This commit prevents such behaviour - instead the\n>> blame is display for any existing lines within the specified range.\n> \n> s/is display/is displayed/ ?\nOops.\n\n> \n> 'git log' has a very similar -L option, which errors out, too, if the\n> end of the line range is past the end of the file.  IMHO the\n> interpretation of the line range -L<start>,<end> should be kept\n> consistent in the two commands, and 'git log' shouldn't error out,\n> either.\nGood suggestion. I'll submit a separate patch for git log.\n\n> \n>> Signed-off-by: Isabella Stephens <istephens@atlassian.com>\n>> ---\n>>  builtin/blame.c               | 4 ++--\n>>  t/t8003-blame-corner-cases.sh | 5 +++--\n>>  2 files changed, 5 insertions(+), 4 deletions(-)\n>>\n>> diff --git a/builtin/blame.c b/builtin/blame.c\n>> index 67adaef4d..b5b9db147 100644\n>> --- a/builtin/blame.c\n>> +++ b/builtin/blame.c\n>> @@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n>>  \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n>>  \t\t\t\t    &bottom, &top, sb.path))\n>>  \t\t\tusage(blame_usage);\n>> -\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n>> +\t\tif ((lno || bottom) && lno < bottom)\n>>  \t\t\tdie(Q_(\"file %s has only %lu line\",\n>>  \t\t\t       \"file %s has only %lu lines\",\n>>  \t\t\t       lno), path, lno);\n>>  \t\tif (bottom < 1)\n>>  \t\t\tbottom = 1;\n>> -\t\tif (top < 1)\n>> +\t\tif (top < 1 || lno < top)\n>>  \t\t\ttop = lno;\n>>  \t\tbottom--;\n>>  \t\trange_set_append_unsafe(&ranges, bottom, top);\n>> diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\n>> index 661f9d430..32b3788fe 100755\n>> --- a/t/t8003-blame-corner-cases.sh\n>> +++ b/t/t8003-blame-corner-cases.sh\n>> @@ -216,8 +216,9 @@ test_expect_success 'blame -L with invalid start' '\n>>  '\n>>  \n>>  test_expect_success 'blame -L with invalid end' '\n>> -\ttest_must_fail git blame -L1,5 tres 2>errors &&\n>> -\ttest_i18ngrep \"has only 2 lines\" errors\n>> +\tgit blame -L1,5 tres >out &&\n>> +\tcat out &&\n>> +\ttest $(wc -l < out) -eq 2\n> \n> Please use the test_line_count helper instead, as it will output a\n> helpful error message on failure, making the 'cat out' above\n> unnecessary.\n> Thanks for pointing that out.\n\n>>  '\n>>  \n>>  test_expect_success 'blame parses <end> part of -L' '\n>> -- \n>> 2.14.1\n>>\n>>\n"},{"id":"331128","messageId":"20171027005652.7796-1-istephens@atlassian.com","threadId":"47031","inReplyTo":"20171026153111.21813-1-szeder.dev@gmail.com","subject":"[PATCH v3] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-27T00:56:52Z","receivedAt":"2017-10-27T00:57:06Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"If the -L option is used to specify a line range in git blame, and the\nend of the range is past the end of the file, at present git will fail\nwith a fatal error. This commit prevents such behavior - instead the\nblame is displayed for existing lines within the specified range.\nBlaming a range that is entirely outside the bounds of the file will\nstill fail.\n\nThis commit also ammends the relevant test and adds clarification to\nthe documentation.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n Documentation/git-blame.txt   | 10 ++++++++++\n builtin/blame.c               |  4 ++--\n t/t8003-blame-corner-cases.sh |  7 +++----\n 3 files changed, 15 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt\nindex fdc3aea30..8a28b4114 100644\n--- a/Documentation/git-blame.txt\n+++ b/Documentation/git-blame.txt\n@@ -154,6 +154,16 @@ Also you can use a regular expression to specify the line range:\n \n which limits the annotation to the body of the `hello` subroutine.\n \n+A range that begins or ends outside the bounds of the file will\n+blame the relevant lines. For example:\n+\n+\tgit blame -L 10,-20 foo\n+\tgit blame -L 10,+20 foo\n+\n+will respectively blame the first 10 and last 11 lines of a\n+20 line file. However, blaming a line range that is entirely\n+outside the bounds of the file will fail.\n+\n When you are not interested in changes older than version\n v2.6.18, or changes older than 3 weeks, you can use revision\n range specifiers  similar to 'git rev-list':\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 67adaef4d..b5b9db147 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n \t\t\t\t    &bottom, &top, sb.path))\n \t\t\tusage(blame_usage);\n-\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n+\t\tif ((lno || bottom) && lno < bottom)\n \t\t\tdie(Q_(\"file %s has only %lu line\",\n \t\t\t       \"file %s has only %lu lines\",\n \t\t\t       lno), path, lno);\n \t\tif (bottom < 1)\n \t\t\tbottom = 1;\n-\t\tif (top < 1)\n+\t\tif (top < 1 || lno < top)\n \t\t\ttop = lno;\n \t\tbottom--;\n \t\trange_set_append_unsafe(&ranges, bottom, top);\ndiff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\nindex 661f9d430..728209fa3 100755\n--- a/t/t8003-blame-corner-cases.sh\n+++ b/t/t8003-blame-corner-cases.sh\n@@ -216,14 +216,13 @@ test_expect_success 'blame -L with invalid start' '\n '\n \n test_expect_success 'blame -L with invalid end' '\n-\ttest_must_fail git blame -L1,5 tres 2>errors &&\n-\ttest_i18ngrep \"has only 2 lines\" errors\n+\tgit blame -L1,5 tres >out &&\n+\ttest_line_count = 2 out\n '\n \n test_expect_success 'blame parses <end> part of -L' '\n \tgit blame -L1,1 tres >out &&\n-\tcat out &&\n-\ttest $(wc -l < out) -eq 1\n+\ttest_line_count = 1 out\n '\n \n test_expect_success 'indent of line numbers, nine lines' '\n-- \n2.14.1\n\n"},{"id":"331134","messageId":"xmqqzi8dcpx1.fsf@gitster.mtv.corp.google.com","threadId":"47031","inReplyTo":"20171027005652.7796-1-istephens@atlassian.com","subject":"Re: [PATCH v3] blame: prevent error if range ends past end of file","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-10-27T01:58:34Z","receivedAt":"2017-10-27T01:58:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Isabella Stephens <istephens@atlassian.com> writes:\n\n> diff --git a/builtin/blame.c b/builtin/blame.c\n> index 67adaef4d..b5b9db147 100644\n> --- a/builtin/blame.c\n> +++ b/builtin/blame.c\n> @@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n>  \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n>  \t\t\t\t    &bottom, &top, sb.path))\n>  \t\t\tusage(blame_usage);\n> -\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n> +\t\tif ((lno || bottom) && lno < bottom)\n>  \t\t\tdie(Q_(\"file %s has only %lu line\",\n>  \t\t\t       \"file %s has only %lu lines\",\n>  \t\t\t       lno), path, lno);\n>  \t\tif (bottom < 1)\n>  \t\t\tbottom = 1;\n> -\t\tif (top < 1)\n> +\t\tif (top < 1 || lno < top)\n>  \t\t\ttop = lno;\n\nThis section sanity-checks first and then tweaks the values it\nallowed to pass the check.  Because it wants to later fix up an\noverly large \"top\" by capping to \"lno\" (i.e. total line number), the\npatch needs to loosen the early sanity-check.  And the \"fixed up\"\nvalues are never checked if they are sane.\n\nFor example, with an empty file (i.e. lno == 0), you can ask \"git\nblame -L1,-4 (\"i.e. \"at most four lines, ending at line #1\") and the\ncode silently accepts the input without noticing that the request is\nan utter nonsense; \"file X has only 0 lines\" error is given a chance\nto kick in.\n\nThere should be an \"is the range sensible?\" check after all the\ntweaking to bottom and top are done, I think.\n\n>  \t\tbottom--;\n>  \t\trange_set_append_unsafe(&ranges, bottom, top);\n> diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\n> index 661f9d430..728209fa3 100755\n> --- a/t/t8003-blame-corner-cases.sh\n> +++ b/t/t8003-blame-corner-cases.sh\n> @@ -216,14 +216,13 @@ test_expect_success 'blame -L with invalid start' '\n>  '\n>  \n>  test_expect_success 'blame -L with invalid end' '\n> -\ttest_must_fail git blame -L1,5 tres 2>errors &&\n> -\ttest_i18ngrep \"has only 2 lines\" errors\n> +\tgit blame -L1,5 tres >out &&\n> +\ttest_line_count = 2 out\n>  '\n>  \n>  test_expect_success 'blame parses <end> part of -L' '\n>  \tgit blame -L1,1 tres >out &&\n> -\tcat out &&\n> -\ttest $(wc -l < out) -eq 1\n> +\ttest_line_count = 1 out\n>  '\n>  \n>  test_expect_success 'indent of line numbers, nine lines' '\n"},{"id":"331135","messageId":"xmqqvaj1cpsq.fsf@gitster.mtv.corp.google.com","threadId":"47031","inReplyTo":"xmqqzi8dcpx1.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3] blame: prevent error if range ends past end of file","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-10-27T02:01:09Z","receivedAt":"2017-10-27T02:01:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> For example, with an empty file (i.e. lno == 0), you can ask \"git\n> blame -L1,-4 (\"i.e. \"at most four lines, ending at line #1\") and the\n> code silently accepts the input without noticing that the request is\n> an utter nonsense; \"file X has only 0 lines\" error is given a chance\n\ns/is given/is not given/; obviously.  Sorry for a typo coming from\nlaggy ssh connection.\n\n> to kick in.\n>\n> There should be an \"is the range sensible?\" check after all the\n> tweaking to bottom and top are done, I think.\n>\n>>  \t\tbottom--;\n>>  \t\trange_set_append_unsafe(&ranges, bottom, top);\n>> diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\n>> index 661f9d430..728209fa3 100755\n>> --- a/t/t8003-blame-corner-cases.sh\n>> +++ b/t/t8003-blame-corner-cases.sh\n>> @@ -216,14 +216,13 @@ test_expect_success 'blame -L with invalid start' '\n>>  '\n>>  \n>>  test_expect_success 'blame -L with invalid end' '\n>> -\ttest_must_fail git blame -L1,5 tres 2>errors &&\n>> -\ttest_i18ngrep \"has only 2 lines\" errors\n>> +\tgit blame -L1,5 tres >out &&\n>> +\ttest_line_count = 2 out\n>>  '\n>>  \n>>  test_expect_success 'blame parses <end> part of -L' '\n>>  \tgit blame -L1,1 tres >out &&\n>> -\tcat out &&\n>> -\ttest $(wc -l < out) -eq 1\n>> +\ttest_line_count = 1 out\n>>  '\n>>  \n>>  test_expect_success 'indent of line numbers, nine lines' '\n"},{"id":"331141","messageId":"926900b8-1aad-b02a-b3c6-2bc4930233fd@atlassian.com","threadId":"47031","inReplyTo":"xmqqzi8dcpx1.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2017-10-27T06:18:20Z","receivedAt":"2017-10-27T06:18:31Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"On 27/10/17 12:58 pm, Junio C Hamano wrote:\n> Isabella Stephens <istephens@atlassian.com> writes:\n> \n>> diff --git a/builtin/blame.c b/builtin/blame.c\n>> index 67adaef4d..b5b9db147 100644\n>> --- a/builtin/blame.c\n>> +++ b/builtin/blame.c\n>> @@ -878,13 +878,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n>>  \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n>>  \t\t\t\t    &bottom, &top, sb.path))\n>>  \t\t\tusage(blame_usage);\n>> -\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n>> +\t\tif ((lno || bottom) && lno < bottom)\n>>  \t\t\tdie(Q_(\"file %s has only %lu line\",\n>>  \t\t\t       \"file %s has only %lu lines\",\n>>  \t\t\t       lno), path, lno);\n>>  \t\tif (bottom < 1)\n>>  \t\t\tbottom = 1;\n>> -\t\tif (top < 1)\n>> +\t\tif (top < 1 || lno < top)\n>>  \t\t\ttop = lno;\n> \n> This section sanity-checks first and then tweaks the values it\n> allowed to pass the check.  Because it wants to later fix up an\n> overly large \"top\" by capping to \"lno\" (i.e. total line number), the\n> patch needs to loosen the early sanity-check.  And the \"fixed up\"\n> values are never checked if they are sane.\n> \n> For example, with an empty file (i.e. lno == 0), you can ask \"git\n> blame -L1,-4 (\"i.e. \"at most four lines, ending at line #1\") and the\n> code silently accepts the input without noticing that the request is\n> an utter nonsense; \"file X has only 0 lines\" error is given a chance\n> to kick in.\n> \n> There should be an \"is the range sensible?\" check after all the\n> tweaking to bottom and top are done, I think.\n\nMy mistake. I missed that case. I think this section of code is a little\nhard to read because it avoids treating an empty file as a special case. \nWhy not do something like this:\n\n  for (range_i = 0; range_i < range_list.nr; ++range_i) {\n          long bottom, top;\n          if (!lno)\n                  die(_(\"file is empty\"));\n          if (parse_range_arg(range_list.items[range_i].string,\n                              nth_line_cb, &sb, lno, anchor,\n                              &bottom, &top, sb.path))\n                  usage(blame_usage);\n          if (bottom < 1)\n                  bottom = 1;\n          if (lno < top)\n                  top = lno;\n          if (top < 0 || lno < bottom)\n                   die(Q_(\"file %s has only %lu line\",\n                         \"file %s has only %lu lines\",\n                         lno), path, lno);\n          bottom--;\n          range_set_append_unsafe(&ranges, bottom, top);\n          anchor = top + 1;\n\nWe'd also need to change parse_range_arg to always make bottom less than top:\n\n-       if (*begin && *end && *end < *begin) {\n+       if (*end < *begin) {\n                SWAP(*end, *begin);\n        }\n\nThis also fixes the case where the given range is n,-(n+1) (e.g. -L1,-2). At\nthe moment that will blame from n to the end of the file. My suggested change\nwould instead blame the first n lines, which makes a lot more sense IMO.\n\nHappy to leave as is if you aren't happy with this suggestion, however.\n"},{"id":"331142","messageId":"CAPig+cSH-y7ChDE_LW55M_wB=KhD7uJHXX=OvZ=1ri5KfYQ5Sg@mail.gmail.com","threadId":"47031","inReplyTo":"926900b8-1aad-b02a-b3c6-2bc4930233fd@atlassian.com","subject":"Re: [PATCH v3] blame: prevent error if range ends past end of file","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2017-10-27T06:56:39Z","receivedAt":"2017-10-27T06:56:44Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Oct 27, 2017 at 2:18 AM, Isabella Stephens\n<istephens@atlassian.com> wrote:\n> On 27/10/17 12:58 pm, Junio C Hamano wrote:\n>> There should be an \"is the range sensible?\" check after all the\n>> tweaking to bottom and top are done, I think.\n>\n> My mistake. I missed that case. I think this section of code is a little\n> hard to read because it avoids treating an empty file as a special case.\n> Why not do something like this:\n>\n>   for (range_i = 0; range_i < range_list.nr; ++range_i) {\n>           long bottom, top;\n>           if (!lno)\n>                   die(_(\"file is empty\"));\n\nNo need for this conditional to reside within the loop. Hoisting it\noutside the loop would (IMO) make the intent even clearer:\n\n    if (range_list.nr && !lno)\n        die(_(\"file is empty; -L has no effect\"));\n    for (...) {\n        ...\n\nOn the other hand, one could argue that \"-L,\" (where comma is the sole\nargument to -L), which specifies the entire file, should be allowed\neven on an empty file without complaining that the file is empty.\nAlthough it may not seem sensible for a human to specify \"-L,\" perhaps\na tool would do so to override an earlier more restrictive -L range.\nHowever, that may be too esoteric a case to worry about.\n\n>           if (parse_range_arg(range_list.items[range_i].string,\n>                               nth_line_cb, &sb, lno, anchor,\n>                               &bottom, &top, sb.path))\n>                   usage(blame_usage);\n>           if (bottom < 1)\n>                   bottom = 1;\n>           if (lno < top)\n>                   top = lno;\n>           if (top < 0 || lno < bottom)\n>                    die(Q_(\"file %s has only %lu line\",\n>                          \"file %s has only %lu lines\",\n>                          lno), path, lno);\n>           bottom--;\n>           range_set_append_unsafe(&ranges, bottom, top);\n>           anchor = top + 1;\n"},{"id":"345878","messageId":"20180426074502.78318-1-istephens@atlassian.com","threadId":"47031","inReplyTo":"CAPig+cSH-y7ChDE_LW55M_wB=KhD7uJHXX=OvZ=1ri5KfYQ5Sg@mail.gmail.com","subject":"[PATCH v4 0/2] blame and log: prevent error if range ends past end of file","fromName":"","fromEmail":"istephens@atlassian.com","sentAt":"2018-04-26T07:45:00Z","receivedAt":"2018-04-26T07:45:19Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"Picking this back up after a little while. This solution means we can still accept\n-L, for an empty file but any other range will fail. I've made the change for both\nblame and log (as two separate patches).\n\nI've also changed behaviour in a couple of corner cases - before we couldn't\ndistinguish between -Ln,-(n+1) and -Ln, so -Ln,-(n+1) would blame from n to the end of\nthe file rather than the first n lines. Also, we now complain that -L,-n is an empty\nrange where previously this would blame the whole file.\n\n"},{"id":"345879","messageId":"20180426074502.78318-2-istephens@atlassian.com","threadId":"47031","inReplyTo":"20180426074502.78318-1-istephens@atlassian.com","subject":"[PATCH v4 1/2] blame: prevent error if range ends past end of file","fromName":"","fromEmail":"istephens@atlassian.com","sentAt":"2018-04-26T07:45:01Z","receivedAt":"2018-04-26T07:47:13Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"From: Isabella Stephens <istephens@atlassian.com>\n\nIf the -L option is used to specify a line range in git blame, and the\nend of the range is past the end of the file, git will fail with a fatal\nerror. This commit prevents such behavior - instead we display the blame\nfor existing lines within the specified range. Tests and documentation\nare ammended accordingly.\n\nThis commit also fixes two corner cases. Blaming -L n,-(n+1) now blames\nthe first n lines of a file rather than from n to the end of the file.\nBlaming -L ,-n will complain of an empty range, rather than blaming the\nwhole file.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n Documentation/git-blame.txt   | 10 ++++++++++\n builtin/blame.c               |  6 ++++--\n line-range.c                  |  2 +-\n t/t8003-blame-corner-cases.sh | 17 +++++++++++++----\n 4 files changed, 28 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt\nindex 16323eb80..8cb81f57a 100644\n--- a/Documentation/git-blame.txt\n+++ b/Documentation/git-blame.txt\n@@ -152,6 +152,16 @@ Also you can use a regular expression to specify the line range:\n \n which limits the annotation to the body of the `hello` subroutine.\n \n+A range that begins or ends outside the bounds of the file will\n+blame the relevant lines. For example:\n+\n+\tgit blame -L 10,-20 foo\n+\tgit blame -L 10,+20 foo\n+\n+will respectively blame the first 10 and last 11 lines of a\n+20 line file. However, blaming a line range that is entirely\n+outside the bounds of the file will fail.\n+\n When you are not interested in changes older than version\n v2.6.18, or changes older than 3 weeks, you can use revision\n range specifiers  similar to 'git rev-list':\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 9dcb367b9..1204ab142 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -886,13 +886,15 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n \t\t\t\t    &bottom, &top, sb.path))\n \t\t\tusage(blame_usage);\n-\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n+\t\tif (!bottom && top < 0)\n+\t\t\tdie(\"-L invalid empty range\");\n+\t\tif ((!lno && (top || bottom)) || lno < bottom)\n \t\t\tdie(Q_(\"file %s has only %lu line\",\n \t\t\t       \"file %s has only %lu lines\",\n \t\t\t       lno), path, lno);\n \t\tif (bottom < 1)\n \t\t\tbottom = 1;\n-\t\tif (top < 1)\n+\t\tif (top < 1 || lno < top)\n \t\t\ttop = lno;\n \t\tbottom--;\n \t\trange_set_append_unsafe(&ranges, bottom, top);\ndiff --git a/line-range.c b/line-range.c\nindex 323399d16..023aee1f5 100644\n--- a/line-range.c\n+++ b/line-range.c\n@@ -47,7 +47,7 @@ static const char *parse_loc(const char *spec, nth_line_fn_t nth_line,\n \t\t\telse if (!num)\n \t\t\t\t*ret = begin;\n \t\t\telse\n-\t\t\t\t*ret = begin + num;\n+\t\t\t\t*ret = begin + num ? begin + num : -1;\n \t\t\treturn term;\n \t\t}\n \t\treturn spec;\ndiff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\nindex 661f9d430..4a0c51658 100755\n--- a/t/t8003-blame-corner-cases.sh\n+++ b/t/t8003-blame-corner-cases.sh\n@@ -216,14 +216,23 @@ test_expect_success 'blame -L with invalid start' '\n '\n \n test_expect_success 'blame -L with invalid end' '\n-\ttest_must_fail git blame -L1,5 tres 2>errors &&\n-\ttest_i18ngrep \"has only 2 lines\" errors\n+\tgit blame -L1,5 tres >out &&\n+\ttest_line_count = 2 out\n '\n \n test_expect_success 'blame parses <end> part of -L' '\n \tgit blame -L1,1 tres >out &&\n-\tcat out &&\n-\ttest $(wc -l < out) -eq 1\n+\ttest_line_count = 1 out\n+'\n+\n+test_expect_success 'blame -Ln,-(n+1)' '\n+\tgit blame -L3,-4 nine_lines >out &&\n+\ttest_line_count = 3 out\n+'\n+\n+test_expect_success 'blame -L,-n' '\n+\ttest_must_fail git blame -L,-1 tres 2>errors &&\n+\ttest_i18ngrep \"-L invalid empty range\"\n '\n \n test_expect_success 'indent of line numbers, nine lines' '\n-- \n2.14.3 (Apple Git-98)\n\n"},{"id":"345880","messageId":"20180426074502.78318-3-istephens@atlassian.com","threadId":"47031","inReplyTo":"20180426074502.78318-1-istephens@atlassian.com","subject":"[PATCH v4 2/2] log: prevent error if line range ends past end of file","fromName":"","fromEmail":"istephens@atlassian.com","sentAt":"2018-04-26T07:45:02Z","receivedAt":"2018-04-26T07:47:35Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"From: Isabella Stephens <istephens@atlassian.com>\n\nIf the -L option is used to specify a line range in git log, and the end\nof the range is past the end of the file, git will fail with a fatal\nerror. This commit prevents such behaviour - instead we perform the log\nfor existing lines within the specified range.\n\nThis commit also fixes a corner case where -L ,-n:file would be treated\nas a log over the whole file. Now we complain that this is an empty\nrange.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n line-log.c          | 10 +++++++---\n t/t4211-line-log.sh | 11 -----------\n 2 files changed, 7 insertions(+), 14 deletions(-)\n\ndiff --git a/line-log.c b/line-log.c\nindex cdc2257db..ad3987062 100644\n--- a/line-log.c\n+++ b/line-log.c\n@@ -599,11 +599,15 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)\n \t\t\t\t    lines, anchor, &begin, &end,\n \t\t\t\t    full_name))\n \t\t\tdie(\"malformed -L argument '%s'\", range_part);\n-\t\tif (lines < end || ((lines || begin) && lines < begin))\n-\t\t\tdie(\"file %s has only %lu lines\", name_part, lines);\n+\t\tif (!begin && end < 0)\n+\t\t\tdie(\"-L invalid empty range\");\n+\t\tif ((!lines && (begin || end)) || lines < begin)\n+\t\t\tdie(Q_(\"file %s has only %lu line\",\n+\t\t\t\t   \"file %s has only %lu lines\",\n+\t\t\t\t   lines), name_part, lines);\n \t\tif (begin < 1)\n \t\t\tbegin = 1;\n-\t\tif (end < 1)\n+\t\tif (end < 1 || lines < end)\n \t\t\tend = lines;\n \t\tbegin--;\n \t\tline_log_data_insert(&ranges, full_name, begin, end);\ndiff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\nindex d0377fae5..0b96496e3 100755\n--- a/t/t4211-line-log.sh\n+++ b/t/t4211-line-log.sh\n@@ -60,7 +60,6 @@ test_bad_opts \"-L 1:nonexistent\" \"There is no path\"\n test_bad_opts \"-L 1:simple\" \"There is no path\"\n test_bad_opts \"-L '/foo:b.c'\" \"argument not .start,end:file\"\n test_bad_opts \"-L 1000:b.c\" \"has only.*lines\"\n-test_bad_opts \"-L 1,1000:b.c\" \"has only.*lines\"\n test_bad_opts \"-L :b.c\" \"argument not .start,end:file\"\n test_bad_opts \"-L :foo:b.c\" \"no match\"\n \n@@ -84,16 +83,6 @@ test_expect_success '-L ,Y (Y == nlines)' '\n \tgit log -L ,$n:b.c\n '\n \n-test_expect_success '-L ,Y (Y == nlines + 1)' '\n-\tn=$(expr $(wc -l <b.c) + 1) &&\n-\ttest_must_fail git log -L ,$n:b.c\n-'\n-\n-test_expect_success '-L ,Y (Y == nlines + 2)' '\n-\tn=$(expr $(wc -l <b.c) + 2) &&\n-\ttest_must_fail git log -L ,$n:b.c\n-'\n-\n test_expect_success '-L with --first-parent and a merge' '\n \tgit checkout parallel-change &&\n \tgit log --first-parent -L 1,1:b.c\n-- \n2.14.3 (Apple Git-98)\n\n"},{"id":"345929","messageId":"xmqq7eot1nhl.fsf@gitster-ct.c.googlers.com","threadId":"47031","inReplyTo":"20180426074502.78318-2-istephens@atlassian.com","subject":"Re: [PATCH v4 1/2] blame: prevent error if range ends past end of file","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-27T00:50:30Z","receivedAt":"2018-04-27T00:50:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"istephens@atlassian.com writes:\n\n> diff --git a/line-range.c b/line-range.c\n> index 323399d16..023aee1f5 100644\n> --- a/line-range.c\n> +++ b/line-range.c\n> @@ -47,7 +47,7 @@ static const char *parse_loc(const char *spec, nth_line_fn_t nth_line,\n>  \t\t\telse if (!num)\n>  \t\t\t\t*ret = begin;\n>  \t\t\telse\n> -\t\t\t\t*ret = begin + num;\n> +\t\t\t\t*ret = begin + num ? begin + num : -1;\n\nWhen parsing \"-L<something>,-20\" to grab some lines before the line\nspecified by <something>, if that something happens to be line #20,\nthis gives -1 to *ret.  If it is line #19, *ret becomes -1, and if\nit is line #18 or before, *ret becomes -2, -3, ...\n\nIs that what we really want here?  It is disturbing that only line\n#19 and #20 are treated identically in the above example.  If it\nwere \"if going backwards by -num lines from begin goes beyond the\nbeginning of the file, clip it to the first line\", I would\nunderstand it, but as written, I am not sure what the code is trying\nto do.\n"},{"id":"345931","messageId":"25cd86ff-a5c0-a968-62d2-4365e5e17a81@atlassian.com","threadId":"47031","inReplyTo":"xmqq7eot1nhl.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v4 1/2] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2018-04-27T01:42:45Z","receivedAt":"2018-04-27T01:42:54Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"My intention was to modify existing behaviour as little as possible,\nbut I agree clipping to the first line makes a lot more sense. That\nraises the question though, do we clip to 1 and treat -L,-n as a valid\ninput, or clip to -1 so that this case be detected?\n\nOn 27/4/18 10:50 am, Junio C Hamano wrote:\n> istephens@atlassian.com writes:\n> \n>> diff --git a/line-range.c b/line-range.c\n>> index 323399d16..023aee1f5 100644\n>> --- a/line-range.c\n>> +++ b/line-range.c\n>> @@ -47,7 +47,7 @@ static const char *parse_loc(const char *spec, nth_line_fn_t nth_line,\n>>  \t\t\telse if (!num)\n>>  \t\t\t\t*ret = begin;\n>>  \t\t\telse\n>> -\t\t\t\t*ret = begin + num;\n>> +\t\t\t\t*ret = begin + num ? begin + num : -1;\n> \n> When parsing \"-L<something>,-20\" to grab some lines before the line\n> specified by <something>, if that something happens to be line #20,\n> this gives -1 to *ret.  If it is line #19, *ret becomes -1, and if\n> it is line #18 or before, *ret becomes -2, -3, ...\n> \n> Is that what we really want here?  It is disturbing that only line\n> #19 and #20 are treated identically in the above example.  If it\n> were \"if going backwards by -num lines from begin goes beyond the\n> beginning of the file, clip it to the first line\", I would\n> understand it, but as written, I am not sure what the code is trying\n> to do.\n> \n"},{"id":"345932","messageId":"xmqq36zh1jtj.fsf@gitster-ct.c.googlers.com","threadId":"47031","inReplyTo":"25cd86ff-a5c0-a968-62d2-4365e5e17a81@atlassian.com","subject":"Re: [PATCH v4 1/2] blame: prevent error if range ends past end of file","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-04-27T02:09:44Z","receivedAt":"2018-04-27T02:09:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Isabella Stephens <istephens@atlassian.com> writes:\n\n> On 27/4/18 10:50 am, Junio C Hamano wrote:\n>> istephens@atlassian.com writes:\n>> \n>>> diff --git a/line-range.c b/line-range.c\n>>> index 323399d16..023aee1f5 100644\n>>> --- a/line-range.c\n>>> +++ b/line-range.c\n>>> @@ -47,7 +47,7 @@ static const char *parse_loc(const char *spec, nth_line_fn_t nth_line,\n>>>  \t\t\telse if (!num)\n>>>  \t\t\t\t*ret = begin;\n>>>  \t\t\telse\n>>> -\t\t\t\t*ret = begin + num;\n>>> +\t\t\t\t*ret = begin + num ? begin + num : -1;\n>> \n>> When parsing \"-L<something>,-20\" to grab some lines before the line\n>> specified by <something>, if that something happens to be line #20,\n>> this gives -1 to *ret.  If it is line #19, *ret becomes -1, and if\n>> it is line #18 or before, *ret becomes -2, -3, ...\n>> \n>> Is that what we really want here?  It is disturbing that only line\n>> #19 and #20 are treated identically in the above example.  If it\n>> were \"if going backwards by -num lines from begin goes beyond the\n>> beginning of the file, clip it to the first line\", I would\n>> understand it, but as written, I am not sure what the code is trying\n>> to do.\n>> \n\n[administrivia] Do not top-post, but cull the context to leave\nenough to remind readers what the discussion was about.\n\n> My intention was to modify existing behaviour as little as possible,\n> but I agree clipping to the first line makes a lot more sense. That\n> raises the question though, do we clip to 1 and treat -L,-n as a valid\n> input, or clip to -1 so that this case be detected?\n\nMaybe I misread the previous discussion and/or your cover letter,\nbut I have been assuming that you are trying to avoid failing the\ncommand in a useless way (e.g. when the file has only ~800 lines but\nthe user does not know exactly how many, instead of letting -L1,820 \nto fail with \"the file only has 815 lines\", pretend that the -L1,815\nwas given) and instead give a reasonable fall-back behaviour.\n\nAnd to be consistent with that world view, I would have expected\nthat the meaning of -L<something>,-20 to be updated from \"fail if\n<something> is before line #20, or show 20 lines leading to\n<something>\" to \"show lines leading to <something>, up to 20 lines\nbut it is OK if there aren't enough lines in the file to show that\nmany\".\n\nSo the answer to the question probably depends on what happens when\n\"this case is detected\" by returning -1 from here.  Do we detect and\nfail?  That would defeat the overall theme of these patches.  Do we\ndetct and warn but continue?  That may be sensible in theory, but in\npractice, especially where this \"the users may not know how many\nlines exactly the blob has, so do not force them to count\" matters,\n\"blame\" and \"log\" would show a lot of output that is sent to the\npager, so the warning message may not be shown in a noticeable way.\nCompared to that, \"pretend as if the first line was specified and go\non\" looks like we have one fewer thing to worry about ;-)\n\n\n"},{"id":"345936","messageId":"dee9083d-0745-6b98-fe5e-fc19d2a5bb9a@atlassian.com","threadId":"47031","inReplyTo":"xmqq36zh1jtj.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v4 1/2] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2018-04-27T04:15:53Z","receivedAt":"2018-04-27T04:16:01Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"> Maybe I misread the previous discussion and/or your cover letter,\n> but I have been assuming that you are trying to avoid failing the\n> command in a useless way (e.g. when the file has only ~800 lines but\n> the user does not know exactly how many, instead of letting -L1,820 \n> to fail with \"the file only has 815 lines\", pretend that the -L1,815\n> was given) and instead give a reasonable fall-back behaviour.\n\nThat's correct. In doing so I picked up on a few extra cases where the\nbehaviour wasn't intuitive, so I've attempted to fix all of those with\nthis patch. \n\n> And to be consistent with that world view, I would have expected\n> that the meaning of -L<something>,-20 to be updated from \"fail if\n> <something> is before line #20, or show 20 lines leading to\n> <something>\" to \"show lines leading to <something>, up to 20 lines\n> but it is OK if there aren't enough lines in the file to show that\n> many\".\n\nThis is the existing behaviour. -L10,-20 for example will blame the\nfirst 10 lines of a file, it will not fail. My patch doesn't change\nthis. The case I am discussing is -L,-20 which at the moment blames\nthe first line of the file. Trying to go backwards from the start of\na file should be considered invalid, in my opinion, however I don't\nfeel strongly about it - I don't expect this case is common in \npractice.\n"},{"id":"346418","messageId":"xmqqzi1iwz7l.fsf@gitster-ct.c.googlers.com","threadId":"47031","inReplyTo":"dee9083d-0745-6b98-fe5e-fc19d2a5bb9a@atlassian.com","subject":"Re: [PATCH v4 1/2] blame: prevent error if range ends past end of file","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-05-02T02:47:26Z","receivedAt":"2018-05-02T02:47:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Isabella Stephens <istephens@atlassian.com> writes:\n\n> This is the existing behaviour. -L10,-20 for example will blame the\n> first 10 lines of a file, it will not fail. My patch doesn't change\n> this. The case I am discussing is -L,-20 which at the moment blames\n> the first line of the file. Trying to go backwards from the start of\n> a file should be considered invalid, in my opinion, however I don't\n> feel strongly about it - I don't expect this case is common in \n> practice.\n\nI tend to think that -L,-20 is a sloppy spelling of -L1,-20\n(i.e. anything omitted gets reasonable default, and for something\nthat specifies both ends, i.e. \"<begin>,<end>\", the beginning and\nthe end of the file would be such reasonable default, respectively),\nand as such I would imagine that the user would expect the same\nbehaviour as -L1,-20.  If the longhand version gives only the first\nline (i.e. show up to 20 lines ending at line #1), I'd say that\nsounds sensible.\n\nOr does -L1,-20 show nothing and consider the input invalid?  If so,\nthen sure, -L,-20 should also be an invalid input.\n\n"},{"id":"348689","messageId":"20180529053037.38015-1-istephens@atlassian.com","threadId":"47031","inReplyTo":"xmqqzi1iwz7l.fsf@gitster-ct.c.googlers.com","subject":"[PATCH v5 0/2] blame and log: prevent error if range ends past end of file","fromName":"","fromEmail":"istephens@atlassian.com","sentAt":"2018-05-29T05:30:35Z","receivedAt":"2018-05-29T05:31:14Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"Okay, I think that sounds reasonable. I've amended the patch so that the\nline number is clipped to 1 when reading in a line range. And -L,-n is now\ntreated the same as -L1,-n i.e. it will blame (or log) the first line of the\nfile only.\n\n"},{"id":"348690","messageId":"20180529053037.38015-2-istephens@atlassian.com","threadId":"47031","inReplyTo":"20180529053037.38015-1-istephens@atlassian.com","subject":"[PATCH] blame: prevent error if range ends past end of file","fromName":"","fromEmail":"istephens@atlassian.com","sentAt":"2018-05-29T05:30:36Z","receivedAt":"2018-05-29T05:31:45Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"From: Isabella Stephens <istephens@atlassian.com>\n\nIf the -L option is used to specify a line range in git blame, and the\nend of the range is past the end of the file, git will fail with a fatal\nerror. This commit prevents such behavior - instead we display the blame\nfor existing lines within the specified range. Tests and documentation\nare ammended accordingly.\n\nThis commit also fixes two corner cases. Blaming -L n,-(n+1) now blames\nthe first n lines of a file rather than from n to the end of the file.\nBlaming -L ,-n will be treated as -L 1,-n and blame the first line of\nthe file, rather than blaming the whole file.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n Documentation/git-blame.txt   | 10 ++++++++++\n builtin/blame.c               |  4 ++--\n line-range.c                  |  2 +-\n t/t8003-blame-corner-cases.sh | 12 ++++++++----\n 4 files changed, 21 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt\nindex 16323eb80..8cb81f57a 100644\n--- a/Documentation/git-blame.txt\n+++ b/Documentation/git-blame.txt\n@@ -152,6 +152,16 @@ Also you can use a regular expression to specify the line range:\n \n which limits the annotation to the body of the `hello` subroutine.\n \n+A range that begins or ends outside the bounds of the file will\n+blame the relevant lines. For example:\n+\n+\tgit blame -L 10,-20 foo\n+\tgit blame -L 10,+20 foo\n+\n+will respectively blame the first 10 and last 11 lines of a\n+20 line file. However, blaming a line range that is entirely\n+outside the bounds of the file will fail.\n+\n When you are not interested in changes older than version\n v2.6.18, or changes older than 3 weeks, you can use revision\n range specifiers  similar to 'git rev-list':\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 9dcb367b9..e1359b192 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -886,13 +886,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\t\t    nth_line_cb, &sb, lno, anchor,\n \t\t\t\t    &bottom, &top, sb.path))\n \t\t\tusage(blame_usage);\n-\t\tif (lno < top || ((lno || bottom) && lno < bottom))\n+\t\tif ((!lno && (top || bottom)) || lno < bottom)\n \t\t\tdie(Q_(\"file %s has only %lu line\",\n \t\t\t       \"file %s has only %lu lines\",\n \t\t\t       lno), path, lno);\n \t\tif (bottom < 1)\n \t\t\tbottom = 1;\n-\t\tif (top < 1)\n+\t\tif (top < 1 || lno < top)\n \t\t\ttop = lno;\n \t\tbottom--;\n \t\trange_set_append_unsafe(&ranges, bottom, top);\ndiff --git a/line-range.c b/line-range.c\nindex 323399d16..232c3909e 100644\n--- a/line-range.c\n+++ b/line-range.c\n@@ -47,7 +47,7 @@ static const char *parse_loc(const char *spec, nth_line_fn_t nth_line,\n \t\t\telse if (!num)\n \t\t\t\t*ret = begin;\n \t\t\telse\n-\t\t\t\t*ret = begin + num;\n+\t\t\t\t*ret = begin + num > 0 ? begin + num : 1;\n \t\t\treturn term;\n \t\t}\n \t\treturn spec;\ndiff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh\nindex 661f9d430..c92a47b6d 100755\n--- a/t/t8003-blame-corner-cases.sh\n+++ b/t/t8003-blame-corner-cases.sh\n@@ -216,14 +216,18 @@ test_expect_success 'blame -L with invalid start' '\n '\n \n test_expect_success 'blame -L with invalid end' '\n-\ttest_must_fail git blame -L1,5 tres 2>errors &&\n-\ttest_i18ngrep \"has only 2 lines\" errors\n+\tgit blame -L1,5 tres >out &&\n+\ttest_line_count = 2 out\n '\n \n test_expect_success 'blame parses <end> part of -L' '\n \tgit blame -L1,1 tres >out &&\n-\tcat out &&\n-\ttest $(wc -l < out) -eq 1\n+\ttest_line_count = 1 out\n+'\n+\n+test_expect_success 'blame -Ln,-(n+1)' '\n+\tgit blame -L3,-4 nine_lines >out &&\n+\ttest_line_count = 3 out\n '\n \n test_expect_success 'indent of line numbers, nine lines' '\n-- \n2.14.3 (Apple Git-98)\n\n"},{"id":"348691","messageId":"20180529053037.38015-3-istephens@atlassian.com","threadId":"47031","inReplyTo":"20180529053037.38015-1-istephens@atlassian.com","subject":"[PATCH] log: prevent error if line range ends past end of file","fromName":"","fromEmail":"istephens@atlassian.com","sentAt":"2018-05-29T05:30:37Z","receivedAt":"2018-05-29T05:31:50Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"From: Isabella Stephens <istephens@atlassian.com>\n\nIf the -L option is used to specify a line range in git log, and the end\nof the range is past the end of the file, git will fail with a fatal\nerror. This commit prevents such behaviour - instead we perform the log\nfor existing lines within the specified range.\n\nThis commit also fixes a corner case where -L ,-n:file would be treated\nas a log over the whole file. Now we treat this as -L 1,-n:file and\nblame the first line of the file instead.\n\nSigned-off-by: Isabella Stephens <istephens@atlassian.com>\n---\n line-log.c          | 8 +++++---\n t/t4211-line-log.sh | 8 +-------\n 2 files changed, 6 insertions(+), 10 deletions(-)\n\ndiff --git a/line-log.c b/line-log.c\nindex cdc2257db..4da40dec1 100644\n--- a/line-log.c\n+++ b/line-log.c\n@@ -599,11 +599,13 @@ parse_lines(struct commit *commit, const char *prefix, struct string_list *args)\n \t\t\t\t    lines, anchor, &begin, &end,\n \t\t\t\t    full_name))\n \t\t\tdie(\"malformed -L argument '%s'\", range_part);\n-\t\tif (lines < end || ((lines || begin) && lines < begin))\n-\t\t\tdie(\"file %s has only %lu lines\", name_part, lines);\n+\t\tif ((!lines && (begin || end)) || lines < begin)\n+\t\t\tdie(Q_(\"file %s has only %lu line\",\n+\t\t\t\t   \"file %s has only %lu lines\",\n+\t\t\t\t   lines), name_part, lines);\n \t\tif (begin < 1)\n \t\t\tbegin = 1;\n-\t\tif (end < 1)\n+\t\tif (end < 1 || lines < end)\n \t\t\tend = lines;\n \t\tbegin--;\n \t\tline_log_data_insert(&ranges, full_name, begin, end);\ndiff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\nindex d0377fae5..c617347c4 100755\n--- a/t/t4211-line-log.sh\n+++ b/t/t4211-line-log.sh\n@@ -60,7 +60,6 @@ test_bad_opts \"-L 1:nonexistent\" \"There is no path\"\n test_bad_opts \"-L 1:simple\" \"There is no path\"\n test_bad_opts \"-L '/foo:b.c'\" \"argument not .start,end:file\"\n test_bad_opts \"-L 1000:b.c\" \"has only.*lines\"\n-test_bad_opts \"-L 1,1000:b.c\" \"has only.*lines\"\n test_bad_opts \"-L :b.c\" \"argument not .start,end:file\"\n test_bad_opts \"-L :foo:b.c\" \"no match\"\n \n@@ -86,12 +85,7 @@ test_expect_success '-L ,Y (Y == nlines)' '\n \n test_expect_success '-L ,Y (Y == nlines + 1)' '\n \tn=$(expr $(wc -l <b.c) + 1) &&\n-\ttest_must_fail git log -L ,$n:b.c\n-'\n-\n-test_expect_success '-L ,Y (Y == nlines + 2)' '\n-\tn=$(expr $(wc -l <b.c) + 2) &&\n-\ttest_must_fail git log -L ,$n:b.c\n+\tgit log -L ,$n:b.c\n '\n \n test_expect_success '-L with --first-parent and a merge' '\n-- \n2.14.3 (Apple Git-98)\n\n"},{"id":"348794","messageId":"CAPig+cTCDP0zJonDFXyv6Kue5y4PMPaveyjfvfTVNoifzYg-Og@mail.gmail.com","threadId":"47031","inReplyTo":"20180529053037.38015-2-istephens@atlassian.com","subject":"Re: [PATCH] blame: prevent error if range ends past end of file","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-05-30T08:45:24Z","receivedAt":"2018-05-30T08:45:45Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, May 29, 2018 at 1:30 AM,  <istephens@atlassian.com> wrote:\n> If the -L option is used to specify a line range in git blame, and the\n> end of the range is past the end of the file, git will fail with a fatal\n> error. This commit prevents such behavior - instead we display the blame\n> for existing lines within the specified range.\n\nMakes sense; the new behavior is intuitive and more friendly.\n\n> Tests and documentation are ammended accordingly.\n\ns/ammended/amended/\n\n> This commit also fixes two corner cases. Blaming -L n,-(n+1) now blames\n> the first n lines of a file rather than from n to the end of the file.\n> Blaming -L ,-n will be treated as -L 1,-n and blame the first line of\n> the file, rather than blaming the whole file.\n>\n> Signed-off-by: Isabella Stephens <istephens@atlassian.com>\n> ---\n> diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt\n> @@ -152,6 +152,16 @@ Also you can use a regular expression to specify the line range:\n>  which limits the annotation to the body of the `hello` subroutine.\n>\n> +A range that begins or ends outside the bounds of the file will\n> +blame the relevant lines. For example:\n> +\n> +       git blame -L 10,-20 foo\n> +       git blame -L 10,+20 foo\n> +\n> +will respectively blame the first 10 and last 11 lines of a\n> +20 line file. However, blaming a line range that is entirely\n> +outside the bounds of the file will fail.\n\nThis documentation seems misplaced. Rather than inserting it after the\ndiscussion of -L/regex/, a more natural place would be just above\n-L/regex/ where -L<begin>,<end> is discussed.\n\nHowever, I am not at all convinced that this behavior should be\ndocumented to this level of detail. Doing so assigns too much emphasis\nto what should be intuitive, thus wastes readers' time wondering why\nit is so heavily emphasized. At _most_, I would think you could say\nmerely:\n\n    A range that begins or ends outside the bounds of the file\n    will be clipped to the file's extent.\n\nand drop the example and discussion of the example results altogether.\n\nIn fact, because this new behavior is what most users will intuitively\nexpect, it might be perfectly reasonable to not say anything about it\nat all (that is, don't modify git-blame.txt).\n\nThanks.\n"},{"id":"348795","messageId":"CAPig+cQ3hRHQM4hOOU9ibOVt3LWvXjNS-VmbK8QWsFFJL=jBvw@mail.gmail.com","threadId":"47031","inReplyTo":"20180529053037.38015-3-istephens@atlassian.com","subject":"Re: [PATCH] log: prevent error if line range ends past end of file","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-05-30T08:59:27Z","receivedAt":"2018-05-30T08:59:34Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, May 29, 2018 at 1:30 AM,  <istephens@atlassian.com> wrote:\n> If the -L option is used to specify a line range in git log, and the end\n> of the range is past the end of the file, git will fail with a fatal\n> error. This commit prevents such behaviour - instead we perform the log\n> for existing lines within the specified range.\n>\n> This commit also fixes a corner case where -L ,-n:file would be treated\n> as a log over the whole file. Now we treat this as -L 1,-n:file and\n> blame the first line of the file instead.\n>\n> Signed-off-by: Isabella Stephens <istephens@atlassian.com>\n> ---\n> diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\n> @@ -86,12 +85,7 @@ test_expect_success '-L ,Y (Y == nlines)' '\n>  test_expect_success '-L ,Y (Y == nlines + 1)' '\n>         n=$(expr $(wc -l <b.c) + 1) &&\n> -       test_must_fail git log -L ,$n:b.c\n> -'\n> -\n> -test_expect_success '-L ,Y (Y == nlines + 2)' '\n> -       n=$(expr $(wc -l <b.c) + 2) &&\n> -       test_must_fail git log -L ,$n:b.c\n> +       git log -L ,$n:b.c\n>  '\n\nNot sure why you removed the 'n+2' test which was added intentionally,\nalong with the 'n' and 'n+1' tests, to probe the boundary handling for\ncorrectness. By eliminating 'n+2', coverage is reduced and, even\nthough your change might be correct at this boundary, some future\nbreaking change might go undetected.\n"},{"id":"348863","messageId":"6c715a0c-2ad1-b2dc-d3d5-d4175632236c@atlassian.com","threadId":"47031","inReplyTo":"CAPig+cTCDP0zJonDFXyv6Kue5y4PMPaveyjfvfTVNoifzYg-Og@mail.gmail.com","subject":"Re: [PATCH] blame: prevent error if range ends past end of file","fromName":"Isabella Stephens","fromEmail":"istephens@atlassian.com","sentAt":"2018-05-31T05:07:57Z","receivedAt":"2018-05-31T05:08:06Z","isPatch":true,"sender":{"key":"istephens@atlassian.com","avatar":"https://avatars.githubusercontent.com/u/30997546?v=4"},"body":"On 30/5/18 6:45 pm, Eric Sunshine wrote:\n>> diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt\n>> @@ -152,6 +152,16 @@ Also you can use a regular expression to specify the line range:\n>>  which limits the annotation to the body of the `hello` subroutine.\n>>\n>> +A range that begins or ends outside the bounds of the file will\n>> +blame the relevant lines. For example:\n>> +\n>> +       git blame -L 10,-20 foo\n>> +       git blame -L 10,+20 foo\n>> +\n>> +will respectively blame the first 10 and last 11 lines of a\n>> +20 line file. However, blaming a line range that is entirely\n>> +outside the bounds of the file will fail.\n> \n> This documentation seems misplaced. Rather than inserting it after the\n> discussion of -L/regex/, a more natural place would be just above\n> -L/regex/ where -L<begin>,<end> is discussed.\n> \n> However, I am not at all convinced that this behavior should be\n> documented to this level of detail. Doing so assigns too much emphasis\n> to what should be intuitive, thus wastes readers' time wondering why\n> it is so heavily emphasized. At _most_, I would think you could say\n> merely:\n> \n>     A range that begins or ends outside the bounds of the file\n>     will be clipped to the file's extent.\n> \n> and drop the example and discussion of the example results altogether.\n> \n> In fact, because this new behavior is what most users will intuitively\n> expect, it might be perfectly reasonable to not say anything about it\n> at all (that is, don't modify git-blame.txt)\nThanks for reviewing Eric. I've submitted a v6 patch in response to your\nfeedback.\n\nI agree that given the behavior is intuitive it's not necessary to\ndocument this change, so I've reverted the change to git-blame.txt\nentirely.\n"}]}