Fix the malformed debian/changelog file
[stand.git] / wodewick
blob2eee4af185fbf62a8547f603fcf7d9e7b8472c7e
1 #!/usr/bin/ruby -w
3 # This is a simple script to automate some of the common checks and
4 # tasks in building a new Debian package of stand. I suggest that you
5 # initially run:
6 #
7 # ./wodewick --changelog <PREVIOUS-VERSION>
8 #
9 # where <PREVIOUS-VERSION> was the version before, and add the output
10 # to debian/changelog
12 # Then run ./wodewick --release or ./wodewick --build
14 # FIXME: add these to the build dependencies:
16 # ruby1.8
17 # libruby1.8
18 # dpkg-dev
19 # perl
21 # FIXME: the .deb file check is actually a pain, since after running
22 # build, that check will fail.
24 require 'getoptlong'
26 def git_current_branch
27 `git branch` =~ /\* ([^\n]+)/m
29 end
31 def git_diff_from_origin_master
32 unless system("git fetch origin master")
33 raise "'git fetch origin master'"
34 end
35 # Now compare our current tree to FETCH_HEAD:
36 `git diff FETCH_HEAD`
37 end
39 def git_tracked_repositories
40 return `git remote`.split("\n")
41 end
43 def last_version_in_changelog
44 return `perl -e 'use Dpkg::Changelog qw(parse_changelog); print parse_changelog->{version}'`
45 end
47 def package_name_in_changelog
48 return `perl -e 'use Dpkg::Changelog qw(parse_changelog); print parse_changelog->{source}'`
49 end
51 def maintainer_email
52 `egrep ^Maintainer: debian/control`.gsub(/^Maintainer: (.*)\n/,'\1')
53 end
55 def wrap(text)
56 result = ""
57 columns = 64
58 while (text.length > columns) && (text.length > 0)
59 index = (text[0...columns] =~ /\s+(\S*?)$/u)
60 unless index
61 if columns < text.length
62 index = columns
63 else
64 index = text.length
65 end
66 end
67 result += text[0...index]
68 text = text[index..-1].gsub( /^\s*/um, '' )
69 if text.length > 0
70 result += "\n"
71 end
72 end
73 result + text
74 end
76 def indent_change(text)
77 result = ""
78 lines = text.split("\n")
79 lines.each_index do |i|
80 if i == 0
81 result += " * #{lines[i]}\n"
82 else
83 result += " #{lines[i]}\n"
84 end
85 end
86 result
87 end
89 def changes_since(commit)
90 result = "#{$package_name} (#{$new_version}) unstable; urgency=low\n\n"
91 current_author = nil
92 lines = `git log --no-merges #{commit}..HEAD | git-shortlog -e`.split("\n")
93 lines.each do |line|
94 if line =~ /^([^ ].*) \(\d+\):$/
95 current_author = $1
96 elsif line =~ /^\s*$/
97 elsif line =~ /^\s{6}(.*)/
98 wrapped = wrap($1)
99 formatted = indent_change(wrapped)
100 result += formatted
101 else
102 raise "Failed to parse a line in the log: '#{line}'"
105 result + "\n -- #{$maintainer_email} #{`date -R`}\n"
108 def usage
109 print <<EOF
110 Usage: wodewick [OPTION]...
112 -h, --help Display this message and exit
113 -c, --check Run pre-packaging checks
114 -b, --build Run pre-packaging checks and build the Debian package
115 -r, --release Run pre-packaging checks, build the Debian package
116 and release (tag, push tags and upload)
117 -l, --changelog <SINCE>
118 Generate changelog entries since commit <SINCE>
119 in a format suitable for a Debian changelog.
124 $origin_exists = nil
125 $new_version = nil
126 $package_name = nil
127 $mantainer_email = nil
129 def check
131 unless system("git --version > /dev/null")
132 raise "Couldn't find git on your $PATH"
135 unless FileTest.exist?("debian/rules")
136 raise "Must be run within a Debian package source directory"
139 unless FileTest.exist?(".git")
140 raise "This must be the top level of a git repository"
143 current_branch = git_current_branch
144 unless current_branch == "master"
145 raise "We're on the branch '#{current_branch}' instead of 'master'"
148 $origin_exists = git_tracked_repositories.include? "origin"
150 # We only run the difference again origin/master if there's a
151 # tracked repository called 'origin'
152 if $origin_exists
154 differences = git_diff_from_origin_master
155 unless differences.empty?
156 raise "There were differences between the working tree and " +
157 "origin/master\nTo see them run: git diff FETCH_HEAD"
162 $new_version = last_version_in_changelog
163 $package_name = package_name_in_changelog
164 $maintainer_email = maintainer_email
166 # If there's a deb with that version in the parent directory, it's a
167 # fair bet that we've forgotten to update the changelog...
169 debs = Dir.glob("../#{$package_name}_#{$new_version}_*.deb")
170 unless debs.empty?
171 message = "The following package files were found:\n "
172 message += debs.join("\n ")
173 message += "\nDid you forget to update debian/changelog ?"
174 raise message
179 def build
181 unless system("dpkg-buildpackage","-rfakeroot")
182 raise "Building the package failed"
187 def release
189 # Tag this relase:
191 unless system("git tag -s version-#{$new_version}")
192 raise "Failed to tag this commit as version-#{$new_version}"
195 # And optionally push those tags:
197 if $origin_exists
198 unless system("git push --tags")
199 raise "Failed to push tags to the origin"
201 end
203 open("last-released-version","w") do |f|
204 f.print $new_version
209 begin
211 options = GetoptLong.new(
212 [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
213 [ "--check", "-c", GetoptLong::NO_ARGUMENT ],
214 [ "--build", "-b", GetoptLong::NO_ARGUMENT ],
215 [ "--release", "-r", GetoptLong::NO_ARGUMENT ],
216 [ "--changelog", "-l", GetoptLong::REQUIRED_ARGUMENT ]
219 help_option = false
220 check_option = false
221 build_option = false
222 release_option = false
223 changelog_option = nil
225 options.each do |opt,arg|
226 case opt
227 when "--help"
228 help_option = true
229 when "--check"
230 check_option = true
231 when "--build"
232 build_option = true
233 when "--release"
234 release_option = true
235 when "--changelog"
236 changelog_option = arg
240 unless (help_option or check_option or build_option or release_option or changelog_option)
241 raise "You must specify an option"
244 # --release subsumes --build, which subsumes --check:
246 if help_option
247 usage
248 elsif changelog_option
249 check
250 s = changes_since(changelog_option)
251 puts s
252 elsif release_option
253 check
254 build
255 release
256 elsif build_option
257 check
258 build
259 elsif check_option
260 check
263 rescue Exception => e
264 puts "Failed: #{e}"