Check that the current directory is named correctly for package building
[stand.git] / wodewick
blob4a7fdbb695407e0986cfee88c5f45db2e5c82ccb
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 `dpkg-parsechangelog | egrep ^Version: | sed 's/^Version: //'`.strip
45 end
47 def package_name_in_changelog
48 return `dpkg-parsechangelog | egrep ^Source: | sed 's/^Source: //'`.strip
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 unless $new_version
164 raise "Failed to find latest version from the changelog"
166 $package_name = package_name_in_changelog
167 unless $package_name
168 raise "Failed to find package name from the changelog"
170 $maintainer_email = maintainer_email
171 unless $maintainer_email
172 raise "Failed to find the maintainer's name and email from the control file"
175 real_directory_name = `readlink -f .`.strip
176 unless real_directory_name =~ /\/#{$package_name}-#{$new_version}$/
177 raise "The directory path must end in #{$package_name}-#{$new_version} (directory path is: #{real_directory_name})"
180 Dir.chdir(real_directory_name)
182 # If there's a deb with that version in the parent directory, it's a
183 # fair bet that we've forgotten to update the changelog...
185 debs = Dir.glob("../#{$package_name}_#{$new_version}_*.deb")
186 unless debs.empty?
187 message = "The following package files were found:\n "
188 message += debs.join("\n ")
189 message += "\nDid you forget to update debian/changelog ?"
190 raise message
195 def build
197 unless system("dpkg-buildpackage","-rfakeroot")
198 raise "Building the package failed"
203 def release
205 # Tag this relase:
207 unless system("git tag -s version-#{$new_version}")
208 raise "Failed to tag this commit as version-#{$new_version}"
211 # And optionally push those tags:
213 if $origin_exists
214 unless system("git push --tags")
215 raise "Failed to push tags to the origin"
217 end
219 open("last-released-version","w") do |f|
220 f.print $new_version
225 begin
227 options = GetoptLong.new(
228 [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
229 [ "--check", "-c", GetoptLong::NO_ARGUMENT ],
230 [ "--build", "-b", GetoptLong::NO_ARGUMENT ],
231 [ "--release", "-r", GetoptLong::NO_ARGUMENT ],
232 [ "--changelog", "-l", GetoptLong::REQUIRED_ARGUMENT ]
235 help_option = false
236 check_option = false
237 build_option = false
238 release_option = false
239 changelog_option = nil
241 options.each do |opt,arg|
242 case opt
243 when "--help"
244 help_option = true
245 when "--check"
246 check_option = true
247 when "--build"
248 build_option = true
249 when "--release"
250 release_option = true
251 when "--changelog"
252 changelog_option = arg
256 unless (help_option or check_option or build_option or release_option or changelog_option)
257 raise "You must specify an option"
260 # --release subsumes --build, which subsumes --check:
262 if help_option
263 usage
264 elsif changelog_option
265 check
266 s = changes_since(changelog_option)
267 puts s
268 elsif release_option
269 check
270 build
271 release
272 elsif build_option
273 check
274 build
275 elsif check_option
276 check
279 rescue Exception => e
280 puts "Failed: #{e}"