Skip to content

Commit ee10b4f

Browse files
committed
Merge branch 'lukas/otp/fix-copyright-update-heuristic/OTP-20297' into maint-28
2 parents d36ae18 + 97161c2 commit ee10b4f

1 file changed

Lines changed: 61 additions & 16 deletions

File tree

scripts/license-header.es

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,12 @@ check_file(File, LargestLicense, Templates, VendorPaths, Opts) ->
268268
Data = read(File, LargestLicense*3),
269269
case re:run(Data, "(.* )?%CopyrightBegin%(?:\r\n|\n)",[]) of
270270
{match, [StartPos | PrefixPos]} ->
271-
check_file_header(File, File, Data, StartPos, PrefixPos, Templates, Opts);
271+
check_file_header(File, File, Data, StartPos, PrefixPos, Templates, VendorPaths, Opts);
272272
nomatch ->
273273
maybe
274274
{ok, LicData} ?= file:read_file(File++".license"),
275275
{match, [StartPos | PrefixPos]} ?= re:run(LicData, "(.* )?%CopyrightBegin%(?:\r\n|\n)",[]),
276-
check_file_header(File, File++".license", LicData, StartPos, PrefixPos, Templates, Opts)
276+
check_file_header(File, File++".license", LicData, StartPos, PrefixPos, Templates, VendorPaths, Opts)
277277
else
278278
_ ->
279279
ReportMissing = not is_ignored(File) andalso
@@ -297,11 +297,11 @@ check_file(File, LargestLicense, Templates, VendorPaths, Opts) ->
297297
erlang:raise(E,R,ST)
298298
end.
299299

300-
check_file_header(File, LicenseFile, Data, StartPos, [], Templates, Opts) ->
301-
check_file_header(File, LicenseFile, Data, StartPos, <<>>, Templates, Opts);
302-
check_file_header(File, LicenseFile, Data, StartPos, [PrefixPos], Templates, Opts) ->
303-
check_file_header(File, LicenseFile, Data, StartPos, binary:part(Data, PrefixPos), Templates, Opts);
304-
check_file_header(File, LicenseFile, Data, {Start, StartEnd}, Prefix, Templates, Opts) ->
300+
check_file_header(File, LicenseFile, Data, StartPos, [], Templates, VendorPaths, Opts) ->
301+
check_file_header(File, LicenseFile, Data, StartPos, <<>>, Templates, VendorPaths, Opts);
302+
check_file_header(File, LicenseFile, Data, StartPos, [PrefixPos], Templates, VendorPaths, Opts) ->
303+
check_file_header(File, LicenseFile, Data, StartPos, binary:part(Data, PrefixPos), Templates, VendorPaths, Opts);
304+
check_file_header(File, LicenseFile, Data, {Start, StartEnd}, Prefix, Templates, VendorPaths, Opts) ->
305305
case re:run(Data, ["\\Q", Prefix, "\\E%CopyrightEnd%(\r\n|\n)"],[]) of
306306
{match, [{End, EndPos},{_,NlSize}]} ->
307307
DataAfterHeader = binary:part(Data, End+EndPos, byte_size(Data) - (End+EndPos)),
@@ -312,8 +312,8 @@ check_file_header(File, LicenseFile, Data, {Start, StartEnd}, Prefix, Templates,
312312
check_license(License, Spdx, Templates,
313313
length(string:split(DataAfterHeader,"\n",all)),
314314
File, not string:equal(File, LicenseFile), Opts),
315-
case maps:get(update, Opts, false) of
316-
true -> update_copyright(LicenseFile, Start + StartEnd, End, Prefix, LineEnding, Spdx, Copyrights, License);
315+
case maps:get(update, Opts, false) andalso not is_vendored(File, VendorPaths) of
316+
true -> update_copyright(File, LicenseFile, Start + StartEnd, End, Prefix, LineEnding, Spdx, Copyrights, License);
317317
false -> ok
318318
end;
319319
nomatch when map_get(verbose, Opts) ->
@@ -322,15 +322,15 @@ check_file_header(File, LicenseFile, Data, {Start, StartEnd}, Prefix, Templates,
322322
throw({warn, "Could not find '~ts %CopyrightEnd%'", [Prefix]})
323323
end.
324324

325-
update_copyright(File, Begin, End, Prefix, LineEnding, Spdx, Copyrights, License) ->
325+
update_copyright(File, LicenseFile, Begin, End, Prefix, LineEnding, Spdx, Copyrights, License) ->
326326
case update_copyright(File, Copyrights) of
327327
Copyrights -> ok;
328328
NewCopyrights ->
329-
{ok, Data} = file:read_file(File),
329+
{ok, Data} = file:read_file(LicenseFile),
330330
Before = binary:part(Data, 0, Begin),
331331
After = binary:part(Data, End, byte_size(Data) - End),
332332
ok = file:write_file(
333-
File,
333+
LicenseFile,
334334
[Before,
335335
string:trim(Prefix, trailing), LineEnding,
336336
Prefix, "SPDX-License-Identifier: ", Spdx, LineEnding,
@@ -351,7 +351,10 @@ update_copyright(File, [C | T]) ->
351351
[C | T];
352352
false ->
353353
LastUpdatedYear = last_updated_year(File,
354-
fun() -> throw({warn,"Could not get copyright year using git log. You need to update it manually.", []}) end),
354+
fun() ->
355+
[throw(skip) || is_ignored(File)],
356+
throw({warn,"Could not get copyright year using git log. You need to update it manually.", []})
357+
end),
355358
case string:equal(LastUpdatedYear, EndYear) of
356359
true ->
357360
[C | T];
@@ -387,11 +390,23 @@ first_updated_year(File, Missing) ->
387390
commit_year(File, Missing, first).
388391

389392
commit_year(File, Missing, When) when When =:= first; When =:= last, is_function(Missing)->
390-
RFC3339Date =
391-
cmd(["git log --format=format:%aI",
393+
394+
Files = follow_renames(File),
395+
396+
%% We use a as in author when looking for the first copyright
397+
%% and we use c as in committer when looking for the last.
398+
%% This is because with an --amend workflow the author date
399+
%% can be a long time in the past, but the committer is when
400+
%% the last change was done.
401+
Modifier = if When =:= first -> "a"; When =:= last -> "c" end,
402+
403+
Cmd = ["git log --format=format:%",Modifier,"I",
392404
[" --reverse" || When =:= first],
393405
" --author='@erlang.org' --author='@ericsson.com'",
394-
" --no-merges HEAD -- ", File, " | head -1"]),
406+
" --no-merges HEAD -- ", [[" '",F,"'"] || F <- Files], " | head -1"],
407+
408+
RFC3339Date = cmd(Cmd),
409+
395410
try calendar:rfc3339_to_system_time(RFC3339Date) of
396411
SystemTime ->
397412
{{YY, _, _}, _} = calendar:system_time_to_local_time(SystemTime,second),
@@ -400,6 +415,35 @@ commit_year(File, Missing, When) when When =:= first; When =:= last, is_function
400415
Missing()
401416
end.
402417

418+
419+
%% Because of problems with git log --follow we implement out own. An example
420+
%% where --follow has issues is for erts/emulator/test/erl_debugger_SUITE_data/gc_test.erl
421+
%% The reason why --follow fails is because gc_test.erl is identified as a copy of
422+
%% another file which is not true.
423+
%%
424+
%% This is all heuristic based so it might make mistakes...
425+
follow_renames(File) ->
426+
follow_renames(File, "HEAD").
427+
follow_renames(File, Sha) ->
428+
429+
maybe
430+
431+
LastCommit = cmd(["git log '--format=format:%H' --no-merges ", Sha, " -- '", File, "' | tail -1"]),
432+
433+
true ?= LastCommit =/= "",
434+
435+
RenameCmd = ["git diff-tree -r -M --name-status \"",LastCommit,"\" | grep '^R[0-9]\\+.*",File,"$' | awk '{ print $2 }'"],
436+
437+
Rename = cmd(RenameCmd),
438+
439+
true ?= Rename =/= "",
440+
441+
[File | follow_renames(Rename, LastCommit)]
442+
else
443+
_ ->
444+
[File]
445+
end.
446+
403447
check_prefix(Prefix, Bin) when is_binary(Bin) ->
404448
case string:split(Bin, "\r\n") of
405449
[Bin] ->
@@ -574,6 +618,7 @@ is_ignored(Filename) ->
574618
"^.mailmap$",
575619
"^OTP_VERSION$",
576620
"^make/otp_patch_solve_forward_merge_version$",
621+
"^make/otp_version_tickets_in_merge$",
577622
"^make/otp_version_tickets$",
578623
"/configure$",
579624
"/config\\.h\\.in",

0 commit comments

Comments
 (0)