2
2
3
3
import os
4
4
import regex
5
+ import subprocess
5
6
import sys
6
7
7
8
from wpiformat .config import Config
@@ -26,15 +27,17 @@ def should_process_file(self, config_file, name):
26
27
return (config_file .is_c_file (name ) or config_file .is_cpp_file (name ) or
27
28
name .endswith (".java" )) and not license_regex .search (name )
28
29
29
- def __try_regex (self , lines , license_template ):
30
+ def __try_regex (self , lines , last_year , license_template ):
30
31
"""Try finding license with regex of license template.
31
32
32
33
Keyword arguments:
33
34
lines -- lines of file
35
+ last_year -- last year in copyright range
34
36
license_template -- license_template string
35
37
36
38
Returns:
37
- Tuple of whether license was found, year, and file contents after license.
39
+ Tuple of whether license was found, first year in copyright range, and
40
+ file contents after license.
38
41
"""
39
42
linesep = Task .get_linesep (lines )
40
43
@@ -47,28 +50,29 @@ def __try_regex(self, lines, license_template):
47
50
license_rgx = regex .compile (license_rgxstr , regex .M )
48
51
49
52
# Compare license
50
- year = self .__current_year
51
53
match = license_rgx .search (lines )
52
54
if match :
53
55
try :
54
- year = match .group ("year" )
56
+ first_year = match .group ("year" )
55
57
except IndexError :
56
58
pass
57
59
58
60
# If comment at beginning of file is non-empty license, update it
59
- return (True , year , linesep + lines [match .end ():].lstrip ())
61
+ return (True , first_year , linesep + lines [match .end ():].lstrip ())
60
62
else :
61
- return (False , year , lines )
63
+ return (False , last_year , lines )
62
64
63
- def __try_string_search (self , lines , license_template ):
65
+ def __try_string_search (self , lines , last_year , license_template ):
64
66
"""Try finding license with string search.
65
67
66
68
Keyword arguments:
67
69
lines -- lines of file
70
+ last_year -- last year in copyright range
68
71
license_template -- license_template string
69
72
70
73
Returns:
71
- Tuple of whether license was found, year, and file contents after license.
74
+ Tuple of whether license was found, first year in copyright range, and
75
+ file contents after license.
72
76
"""
73
77
linesep = Task .get_linesep (lines )
74
78
@@ -107,8 +111,9 @@ def __try_string_search(self, lines, license_template):
107
111
else :
108
112
license_end += 1
109
113
114
+ first_year = last_year
115
+
110
116
# If comment at beginning of file is non-empty license, update it
111
- year = self .__current_year
112
117
if first_comment_is_license and license_end > 0 :
113
118
license_part = linesep .join (stripped_lines [0 :license_end ])
114
119
appendix_part = \
@@ -119,33 +124,51 @@ def __try_string_search(self, lines, license_template):
119
124
match = year_regex .search (line )
120
125
# If license contains copyright pattern, extract the first year
121
126
if match :
122
- year = match .group (1 )
127
+ first_year = match .group (1 )
123
128
break
124
129
125
- return (True , year , appendix_part )
130
+ return (True , first_year , appendix_part )
126
131
else :
127
- return (False , year , linesep + lines .lstrip ())
132
+ return (False , first_year , linesep + lines .lstrip ())
128
133
129
134
def run_pipeline (self , config_file , name , lines ):
130
135
linesep = Task .get_linesep (lines )
131
136
132
137
license_template = Config .read_file (
133
138
os .path .dirname (os .path .abspath (name )), ".styleguide-license" )
134
139
135
- success , year , appendix = self .__try_regex (lines , license_template )
140
+ # Get year when file was most recently modified in Git history
141
+ #
142
+ # Committer date is used instead of author date (the one shown by "git
143
+ # log" because the year the file was last modified in the history should
144
+ # be used. Author dates can be older than this or even out of order in
145
+ # the log.
146
+ cmd = ["git" , "log" , "-n" , "1" , "--format=%ci" , "--" , name ]
147
+ last_year = subprocess .run (cmd ,
148
+ stdout = subprocess .PIPE ).stdout .decode ()[:4 ]
149
+
150
+ # If file hasn't been committed yet, use current calendar year as end of
151
+ # copyright year range
152
+ if last_year == "" :
153
+ last_year = self .__current_year
154
+
155
+ success , first_year , appendix = self .__try_regex (
156
+ lines , last_year , license_template )
136
157
if not success :
137
- success , year , appendix = self .__try_string_search (
138
- lines , license_template )
158
+ success , first_year , appendix = self .__try_string_search (
159
+ lines , last_year , license_template )
139
160
140
161
output = ""
141
162
142
163
# Determine copyright range and trailing padding
143
- if year != self .__current_year :
144
- year = year + "-" + self .__current_year
164
+ if first_year != last_year :
165
+ year_range = first_year + "-" + last_year
166
+ else :
167
+ year_range = first_year
145
168
146
169
for line in license_template :
147
170
# Insert copyright year range
148
- line = line .replace ("{year}" , year )
171
+ line = line .replace ("{year}" , year_range )
149
172
150
173
# Insert padding which expands to the 80th column. If there is more
151
174
# than one padding token, the line may contain fewer than 80
0 commit comments