Merge lp:~henninge/launchpad/devel-update-copyright into lp:launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 11645
Proposed branch: lp:~henninge/launchpad/devel-update-copyright
Merge into: lp:launchpad
Diff against target: 203 lines (+135/-41)
3 files modified
buildout-templates/bin/lint.sh.in (+3/-41)
utilities/find-changed-files.sh (+45/-0)
utilities/update-copyright (+87/-0)
To merge this branch: bzr merge lp:~henninge/launchpad/devel-update-copyright
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+36701@code.launchpad.net

Commit message

New utility scripts: find-changed-files.sh and update-copyright.

Description of the change

Adds a little script that updates the year information in the copyright header of all changed files. This should make it easy to keep them up to date.

I extracted the code that finds changed files using bzr from lint.sh, which is used by 'make lint'.

No test, this is just a little helper script. Use "bzr diff" after a run to see that it worked.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you so much for this.

review: Approve (code)
Revision history for this message
Robert Collins (lifeless) wrote :

There is a bzr plugin that can do this without it being in the LP
source tree. It would be nicer to use that.

Revision history for this message
Brad Crittenden (bac) wrote :

I'm glad to learn of bzr-update-copyright.

Unfortunately when we first put the copyright notice in the files we started with 2009. Using the bzr plugin will change that to use the actual years the file was touched. IANACL so I don't know which is correct but I'd like that to be a decision we make rather than whatever the tool currently writes, so I'd discourage use of the bzr plugin until we can agree.

Note the two tools do not coexist well now as Henning's uses collapsed year ranges, which we prefer, (e.g. "2009-2010") while the plugin produces a comma-separated list. Once the latter is put in the code then this tool is broken.

Perhaps the best effort would be towards improving the plugin.

I'd like for us to get one or the other b/c we spend a lot of time fixing silly copyright notices or leaving them wrong.

Revision history for this message
Robert Collins (lifeless) wrote :

I'd like to see the bzr plugin improved if its insufficient. Perhaps a
file in the bzr extensions namespace in the tree, with a config file
to say (use -, and start in 2009).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout-templates/bin/lint.sh.in'
2--- buildout-templates/bin/lint.sh.in 2010-07-17 21:42:06 +0000
3+++ buildout-templates/bin/lint.sh.in 2010-09-28 07:58:44 +0000
4@@ -1,6 +1,6 @@
5 #!/bin/bash
6 #
7-# Copyright 2009 Canonical Ltd. This software is licensed under the
8+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
9 # GNU Affero General Public License version 3 (see the file LICENSE).
10 #
11 # Runs pocketlint on files changed from parent branch.
12@@ -12,47 +12,9 @@
13 [ -z "$utilitiesdir" ] && utilitiesdir=.
14
15
16-bzr() {
17- # For pylint to operate properly, PYTHONPATH must point to the ./lib
18- # directory in the launchpad tree. This directory includes a bzrlib. When
19- # this script calls bzr, we want it to use the system bzrlib, not the one
20- # in the launchpad tree.
21- PYTHONPATH='' `which bzr` "$@"
22-}
23-
24-
25 if [ -z "$1" ]; then
26- # No command line argument provided, use the default logic.
27- bzr diff > /dev/null
28- diff_status=$?
29- if [ $diff_status -eq 0 ] ; then
30- # No uncommitted changes in the tree.
31- bzr status | grep "^Current thread:" > /dev/null
32- if [ $? -eq 0 ] ; then
33- # This is a loom, lint changes relative to the lower thread.
34- rev_option="-r thread:"
35- else
36- if test "$(bzr pipes | sed -n -e "/^\\*/q;p" | wc -l)" -gt 0; then
37- # This is a pipeline with at least one pipe before the
38- # current, lint changes relative to the previous pipe
39- rev_option="-r ancestor::prev"
40- else
41- # Lint changes relative to the parent.
42- rev=`bzr info | sed \
43- '/parent branch:/!d; s/ *parent branch: /ancestor:/'`
44- rev_option="-r $rev"
45- fi
46- fi
47- elif [ $diff_status -eq 1 ] ; then
48- # Uncommitted changes in the tree, lint those changes.
49- rev_option=""
50- else
51- # bzr diff failed
52- exit 1
53- fi
54- # Extract filename from status line. Strip the @ that mark symlinks.
55- files=`bzr st --short $rev_option |
56- sed -e '/^.[MN]/!d; s/.* //' -e 's/@$//'`
57+ # No command line argument provided, lint all changed files.
58+ files=$($utilitiesdir/find-changed-files.sh)
59 else
60 # Add newlines so grep filters out pyfiles correctly later.
61 files=`echo $* | tr " " "\n"`
62
63=== added file 'utilities/find-changed-files.sh'
64--- utilities/find-changed-files.sh 1970-01-01 00:00:00 +0000
65+++ utilities/find-changed-files.sh 2010-09-28 07:58:44 +0000
66@@ -0,0 +1,45 @@
67+#!/bin/bash
68+#
69+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
70+# GNU Affero General Public License version 3 (see the file LICENSE).
71+#
72+# Determine the changed files in Bazaar piplines, looms and plain branches.
73+
74+bzr() {
75+ # PYTHONPATH may point to the ./lib directory in the launchpad tree. This
76+ # directory includes a bzrlib. When this script calls bzr, we want it to
77+ # use the system bzrlib, not the one in the launchpad tree.
78+ PYTHONPATH='' `which bzr` "$@"
79+}
80+
81+bzr diff > /dev/null
82+diff_status=$?
83+if [ $diff_status -eq 0 ] ; then
84+ # No uncommitted changes in the tree.
85+ bzr status | grep "^Current thread:" > /dev/null
86+ if [ $? -eq 0 ] ; then
87+ # This is a loom, lint changes relative to the lower thread.
88+ rev_option="-r thread:"
89+ elif [ "$(bzr pipes | sed -n -e "/^\\*/q;p" | wc -l)" -gt 0 ]; then
90+ # This is a pipeline with at least one pipe before the
91+ # current, lint changes relative to the previous pipe
92+ rev_option="-r ancestor::prev"
93+ else
94+ # Lint changes relative to the parent.
95+ rev=`bzr info | sed \
96+ '/parent branch:/!d; s/ *parent branch: /ancestor:/'`
97+ rev_option="-r $rev"
98+ fi
99+elif [ $diff_status -eq 1 ] ; then
100+ # Uncommitted changes in the tree, return those files.
101+ rev_option=""
102+else
103+ # bzr diff failed
104+ exit 1
105+fi
106+# Extract filename from status line. Strip the @ that mark symlinks.
107+files=`bzr st --short $rev_option |
108+ sed -e '/^.[MN]/!d; s/.* //' -e 's/@$//'`
109+
110+echo $files
111+
112
113=== added file 'utilities/update-copyright'
114--- utilities/update-copyright 1970-01-01 00:00:00 +0000
115+++ utilities/update-copyright 2010-09-28 07:58:44 +0000
116@@ -0,0 +1,87 @@
117+#!/usr/bin/python
118+#
119+# Copyright 2010 Canonical Ltd. This software is licensed under the
120+# GNU Affero General Public License version 3 (see the file LICENSE).
121+
122+"""Update the year in copyright notices.
123+
124+This simple script determines the changed files and updates the copyright
125+notice to reflect the current year. Looks for the notice in the first three
126+lines of the file and leaves the file unchanged if it finds none.
127+"""
128+
129+from datetime import date
130+import os
131+import re
132+from subprocess import (
133+ PIPE,
134+ Popen,
135+ )
136+import sys
137+
138+
139+# This script lives in the 'utilites' directory.
140+UTILITIES_DIR = os.path.dirname(__file__)
141+CURRENT_YEAR = date.today().year
142+copyright_pattern = re.compile(
143+ "Copyright (?P<years>(?P<yearfrom>[0-9]{4})(-[0-9]{4})?) Canonical Ltd.")
144+
145+def years_string(yearfrom):
146+ """Build the new years string."""
147+ if int(yearfrom) >= CURRENT_YEAR:
148+ return yearfrom
149+ return "%s-%d" % (yearfrom, CURRENT_YEAR)
150+
151+def update_copyright(lines):
152+ """Update the copyright notice in the given file lines."""
153+ for line in range(min(len(lines), 3)):
154+ match = copyright_pattern.search(lines[line])
155+ if match is not None:
156+ old_years = match.group('years')
157+ new_years = years_string(match.group('yearfrom'))
158+ if old_years != new_years:
159+ lines[line] = lines[line].replace(old_years, new_years)
160+ return True
161+ return False
162+ return False
163+
164+
165+def update_files(filenames):
166+ """Open the files with the given file names and update them."""
167+ for filename in filenames:
168+ if not os.path.isfile(filename):
169+ print "Skipped: %s does not exist or is not a regular file." %(
170+ filename)
171+ continue
172+ if not os.access(filename, os.W_OK):
173+ print "Skipped: %s is not writeable." % filename
174+ continue
175+ lines = file(filename).readlines()
176+ changed = update_copyright(lines)
177+ if changed:
178+ newfile = open(filename, 'w')
179+ newfile.write(''.join(lines))
180+ newfile.close()
181+ print "Updated: %s" % filename
182+ else:
183+ print "Unchanged: %s" % filename
184+
185+def find_changed_files():
186+ """Use the find-changed-files.sh script."""
187+ find_changed_files_cmd = [
188+ os.path.join(UTILITIES_DIR, 'find-changed-files.sh')]
189+ filenames = Popen(find_changed_files_cmd, stdout=PIPE).communicate()[0]
190+ return filenames.strip()
191+
192+def find_and_update():
193+ """Put it all together."""
194+ filenames = find_changed_files()
195+ if filenames != '':
196+ update_files(filenames.split(' '))
197+
198+if __name__ == "__main__":
199+ if len(sys.argv) < 2:
200+ find_and_update()
201+ else:
202+ update_files(sys.argv[1:])
203+