script to retroactively add commitids to past openbsd commits
1#
2# Copyright (c) 2014, 2016 joshua stein <jcs@jcs.org>
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions
6# are met:
7#
8# 1. Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11# notice, this list of conditions and the following disclaimer in the
12# documentation and/or other materials provided with the distribution.
13# 3. The name of the author may not be used to endorse or promote products
14# derived from this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27
28require "shellwords"
29
30class Outputter
31 def initialize(scanner)
32 @scanner = scanner
33 end
34
35 def changelog(domain, fh)
36 puts "writing changelog to #{fh.path}"
37
38 last = {}
39 files = []
40
41 printlog = Proc.new {
42 fh.puts "Changes by: #{last["author"]}@#{domain} " <<
43 Time.at(last["date"].to_i).strftime("%Y/%m/%d %H:%M:%S")
44 if last["commitid"].to_s != ""
45 fh.puts "Commitid: #{last["commitid"]}"
46 end
47 if last["branch"].to_s != ""
48 fh.puts "Branch: #{last["branch"]}"
49 end
50 fh.puts ""
51 fh.puts "Modified files:"
52
53 # group files by directory
54 dirs = {}
55 files.each do |f|
56 dir = f.split("/")
57 file = dir.pop.gsub(/,v$/, "")
58
59 if dir.length == 0
60 dir = "."
61 else
62 dir = dir.join("/")
63 end
64
65 dirs[dir] ||= []
66 if !dirs[dir].include?(file)
67 dirs[dir].push file
68 end
69 end
70
71 # print padded and wrapped directory and file lines
72 dirs.each do |dir,fs|
73 dl = " #{dir}"
74 if dir.length < 15
75 (15 - dir.length).times do
76 dl += " "
77 end
78 end
79 dl += ":"
80 fl = (72 - dl.length)
81 cl = dl
82 (fs.count + 1).times do
83 if (f = fs.shift)
84 if cl.length + f.length > 72
85 fh.puts cl.gsub(/[ ]{8}/, "\t")
86 cl = " " * dl.length
87 end
88
89 cl += " " + f
90 else
91 fh.puts cl.gsub(/[ ]{8}/, "\t")
92 break
93 end
94 end
95 end
96
97 fh.puts ""
98 fh.puts "Log message:"
99 fh.puts last["log"]
100 fh.puts ""
101 fh.puts ""
102 }
103
104 @scanner.db.execute("SELECT
105 changesets.csorder, changesets.date, changesets.author,
106 changesets.commitid, changesets.log, files.file, revisions.branch
107 FROM changesets
108 LEFT OUTER JOIN revisions ON revisions.changeset_id = changesets.id
109 LEFT OUTER JOIN files ON revisions.file_id = files.id
110 ORDER BY changesets.csorder, files.file") do |csfile|
111 if csfile["csorder"] == last["csorder"]
112 files.push csfile["file"]
113 else
114 if files.any?
115 printlog.call
116 end
117 files = [ csfile["file"] ]
118 last = csfile
119 end
120 end
121
122 if last.any?
123 printlog.call
124 end
125 end
126
127 def history(fh)
128 puts "writing history to #{fh.path}"
129
130 last = {}
131 files = []
132
133 printlog = Proc.new {
134 fh.puts [
135 Time.at(last["date"].to_i).strftime("%Y/%m/%d %H:%M:%S"),
136 last["author"],
137 last["commitid"],
138 last["log"].to_s.split("\n").first,
139 files.map{|f| f.gsub(/,v$/, "") }.join(", "),
140 ].join("\t")
141 }
142
143 @scanner.db.execute("SELECT
144 changesets.date, changesets.author, changesets.commitid, changesets.log,
145 files.file
146 FROM changesets
147 LEFT OUTER JOIN revisions ON revisions.changeset_id = changesets.id
148 LEFT OUTER JOIN files ON revisions.file_id = files.id
149 ORDER BY changesets.date, files.file") do |csfile|
150 if csfile["commitid"] == last["commitid"]
151 files.push csfile["file"]
152 else
153 if files.any?
154 printlog.call
155 end
156 files = [ csfile["file"] ]
157 last = csfile
158 end
159 end
160
161 if last.any?
162 printlog.call
163 end
164 end
165
166 def dup_script(script, tree)
167 puts "writing update script to #{script.path}"
168
169 script.puts "#!/bin/sh -x"
170 script.puts "if [ \"$TMPCVSDIR\" = \"\" ]; then echo 'set $TMPCVSDIR'; " +
171 "exit 1; fi"
172 script.puts "if [ \"$CVSROOT\" = \"\" ]; then echo 'set $CVSROOT'; " +
173 "exit 1; fi"
174 script.puts ""
175 script.puts "set -e"
176 script.puts ""
177 script.puts "cd $TMPCVSDIR"
178 script.puts "cvs -Q -d $CVSROOT co -r1.1 #{tree}"
179 script.puts ""
180
181 dead11s = {}
182 @scanner.db.execute("SELECT
183 file, first_undead_version
184 FROM files
185 WHERE first_undead_version NOT LIKE '1.1'") do |rev|
186 dead11s[rev["file"]] = rev["first_undead_version"]
187 end
188
189 dead11s.each do |file,rev|
190 confile = file.gsub(/,v$/, "")
191
192 script.puts "cvs -Q -d $CVSROOT co -r#{rev} " +
193 "#{tree}/#{Shellwords.escape(confile)}"
194 end
195
196 script.puts ""
197 script.puts "cd $TMPCVSDIR/#{tree}"
198
199 csid = nil
200 @scanner.db.execute("SELECT
201 files.file, changesets.commitid, changesets.author, changesets.date,
202 revisions.version, changesets.branch
203 FROM revisions
204 LEFT OUTER JOIN files ON files.id = file_id
205 LEFT OUTER JOIN changesets ON revisions.changeset_id = changesets.id
206 ORDER BY changesets.csorder ASC, files.file ASC") do |rev|
207 if csid == nil || rev["commitid"] != csid
208 script.puts "# #{Time.at(rev["date"])} by " + rev["author"] +
209 (rev["branch"].to_s == "" ? "" : " (branch #{rev["branch"]})")
210 csid = rev["commitid"]
211 script.puts "COMMITID=\"#{Shellwords.escape(rev["commitid"])}\""
212 end
213
214 fi = rev["file"].gsub(/,v$/, "")
215 script.puts "cvs admin -C #{rev["version"]}:${COMMITID} " +
216 "#{Shellwords.escape(fi)}"
217 end
218 end
219end