Skip to content
Newer
Older
100755 476 lines (401 sloc) 15.5 KB
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
1 #!/usr/bin/env ruby
648f1b6 Add author header and a note about running in a empty directory
Steve authored Oct 11, 2007
2 ##
3 ## Author: Steve Purcell, http://www.sanityinc.com/
4 ## Obtain the latest version of this software here: http://git.sanityinc.com/
5 ##
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
6
ea74920 @nominolo Update TODOs
nominolo authored May 9, 2008
7 # XXX: make backwards compatible
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
8 # TODO: import parallel darcs repos as git branches, identifying branch points
ea74920 @nominolo Update TODOs
nominolo authored May 8, 2008
9 # TODO: use default repo if none was supplied
ae775b5 @purcell Return to storing darcs-hash in commit comments, but provide an optio…
authored May 12, 2008
10 # TODO: handle *-darcs-backupN files?
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
11
12 require 'ostruct'
13 require 'rexml/document'
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
14 require 'optparse'
76cbfc2 @nominolo Allow listing of authors
nominolo authored May 9, 2008
15 require 'yaml'
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
16
c547c01 @nominolo Proper handling of timezones
nominolo authored May 7, 2008
17 # Explicitly setting a time zone would cause darcs to only output in
18 # that timezone hence we couldn't get the actual patch TZ
19 # ENV['TZ'] = 'GMT0'
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
20
c213d24 @nominolo Move darcs hashes out of commit messages. By default they now go into
nominolo authored May 7, 2008
21 GIT_PATCHES = ".git/darcs_patches"
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 11, 2008
22 DEFAULT_AUTHOR_MAP_FILE = ".git/darcs_author_substitutions"
23
24 # -------------------------------------------------------------------------------
25 # Usage info and argument parsing
26 # -------------------------------------------------------------------------------
b0d3292 @purcell Add more details usage info, as requested by Samuel Bronson
authored Feb 17, 2008
27
6e40cd3 @nominolo Add some more options
nominolo authored May 9, 2008
28 OPTIONS = { :default_email => nil,
29 :list_authors => false,
30 :author_map => nil,
ae775b5 @purcell Return to storing darcs-hash in commit comments, but provide an optio…
authored May 12, 2008
31 :clean_commit_messages => false,
f5bf94d @purcell Clean up logic linking --patches option and running of post-flight co…
authored May 12, 2008
32 :num_patches => nil }
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
33 opts = OptionParser.new do |opts|
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
34 opts.banner = <<-end_usage
35 Creates git repositories from darcs repositories
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
36
37 usage: darcs-to-git DARCSREPODIR [options]
b0d3292 @purcell Add more details usage info, as requested by Samuel Bronson
authored Feb 17, 2008
38
39
40 1. Create an *empty* directory that will become the new git repository
41 2. From inside that directory, run this program, passing the location
ada5bc8 @asjo Hint at the fact that the darcs repository must be a local one.
asjo authored Mar 19, 2008
42 of the local source darcs repo as a parameter
b0d3292 @purcell Add more details usage info, as requested by Samuel Bronson
authored Feb 17, 2008
43
44 The program will git-init the empty directory, and migrate all patches
45 in the source darcs repo into commits in that repository.
46
47 Thereafter, incremental patch conversion from the same source repo is
48 possible by repeating step 2.
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
49
53218c8 @nominolo Document that only the first tag will be applied.
nominolo authored May 7, 2008
50 NOTE: In case of multiple tags, only the first one will be applied.
51 If you really need to, you can manually identify the patch and use
52 \"git tag -f <tagname> <sha1-of-commit-before-tagging>\".
53
54 OPTIONS
55
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
56 end_usage
1311774 @nominolo Remove short options
nominolo authored May 9, 2008
57 opts.on('--default-email ADDRESS',
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
58 "Set the email address used when no explicit address is given") do |m|
6e40cd3 @nominolo Add some more options
nominolo authored May 8, 2008
59 OPTIONS[:default_email] = m
60 end
1311774 @nominolo Remove short options
nominolo authored May 9, 2008
61 opts.on('--list-authors',
6e40cd3 @nominolo Add some more options
nominolo authored May 8, 2008
62 "List all unique authors in source repo and quit.") do |m|
63 OPTIONS[:list_authors] = m
64 end
1311774 @nominolo Remove short options
nominolo authored May 9, 2008
65 opts.on('--author-map FILE',
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
66 "Supply a YAML file that maps committer names to canonical author names") do |f|
6e40cd3 @nominolo Add some more options
nominolo authored May 8, 2008
67 OPTIONS[:author_map] = f
68 end
69 opts.on('--patches [N]', OptionParser::DecimalInteger,
70 "Only pull N patches.") do |n|
f5bf94d @purcell Clean up logic linking --patches option and running of post-flight co…
authored May 12, 2008
71 abort opts.to_s unless n >= 0
6e40cd3 @nominolo Add some more options
nominolo authored May 8, 2008
72 OPTIONS[:num_patches] = n
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
73 end
ae775b5 @purcell Return to storing darcs-hash in commit comments, but provide an optio…
authored May 12, 2008
74 opts.on('--clean-commit-messages',
75 "Don't note darcs hashes in git commit messages (not recommended)") do |n|
76 OPTIONS[:clean_commit_messages] = true
77 end
2690e4b @purcell Add a --help option
authored May 12, 2008
78 opts.on('-h', '--help', "Show this message") do
3b11516 exit with 0, not 1 if explicitly called with --help or -h
Simon Huerlimann authored Jan 2, 2009
79 puts opts.to_s
80 exit
2690e4b @purcell Add a --help option
authored May 12, 2008
81 end
24157c1 @nominolo Add argument handling and add argument for default email address
nominolo authored May 7, 2008
82 end
83 opts.parse!
84
85 SRCREPO = ARGV[0]
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
86 if SRCREPO.nil?
2690e4b @purcell Add a --help option
authored May 12, 2008
87 abort opts.to_s
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
88 elsif !FileTest.exists?(SRCREPO + '/_darcs')
89 abort "#{SRCREPO} is not a valid local darcs repository"
de433de @purcell Add -h/--help switches (requested by Brenda Wallace)
authored Feb 17, 2008
90 end
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
91
bd442b4 @purcell Move DarcsPatch#decode_darcs_escape to String#darcs_unescape
authored May 10, 2008
92
93 # -------------------------------------------------------------------------------
94 # Utilities
95 # -------------------------------------------------------------------------------
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
96 def run(*args)
97 puts "Running: #{args.inspect}"
98 system(*args) || raise("Failed to run: #{args.inspect}")
99 end
100
101 def output_of(*args)
102 puts "Running: #{args.inspect}"
103 output = IO.popen(args.map {|a| "'#{a}'"}.join(' '), 'r') { |p| p.read }
104 if $?.exitstatus == 0
105 return output
106 else
107 raise "Failed to run: #{args.inspect}"
108 end
109 end
110
a110c04 @purcell Provide and use Symbol#to_proc
authored May 11, 2008
111 class Symbol
112 def to_proc() lambda { |o| o.send(self) } end
113 end
114
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
115 class String
bd442b4 @purcell Move DarcsPatch#decode_darcs_escape to String#darcs_unescape
authored May 10, 2008
116 def darcs_unescape
117 # darcs uses '[_\hh_]' to quote non-ascii characters where 'h' is
118 # a hexadecimal. We translate this to '=hh' and use ruby's unpack
119 # to do replace this with the proper byte.
120 gsub(/\[\_\\(..)\_\]/) { |x| "=#{$1}" }.unpack("M*")[0]
121 end
122 end
123
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
124
125 # -------------------------------------------------------------------------------
126 # Map darcs authors to git authors
127 # -------------------------------------------------------------------------------
128 class AuthorMap < Hash
129 attr_accessor :default_email
130
131 def self.load(filename)
132 new.merge(YAML.load_file(filename))
133 end
134
135 # gives the name and email
136 def [](author)
137 name_and_email(super || author)
138 end
139
140 private
141
142 def name_and_email(author)
40bb362 @purcell Tidy up author/email regex code
authored May 12, 2008
143 case author
144 when /^\s*(\S.*?)\s*\<(\S+@\S+?)\>\s*$/
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
145 [$1, $2]
40bb362 @purcell Tidy up author/email regex code
authored May 12, 2008
146 when /^\s*\<?(\S+@\S+?)\>?\s*$/
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
147 email = $1
148 [email.split('@').first, email]
149 else
150 [author, default_email]
151 end
152 end
153 end
154
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
155 # -------------------------------------------------------------------------------
156 # Storing a history of related darcs and git commits
157 # -------------------------------------------------------------------------------
158
159 class CommitHistory
160 def initialize(patch_file_name)
161 @patch_file_name = patch_file_name
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
162 @darcs_patches_in_git = {}
163 if File.exists?(patch_file_name)
164 @darcs_patches_in_git = YAML.load_file(patch_file_name)
165 unless @darcs_patches_in_git.is_a?(Hash)
166 raise "yaml hash not found in #{patch_file_name}"
167 end
168 else
ae775b5 @purcell Return to storing darcs-hash in commit comments, but provide an optio…
authored May 12, 2008
169 # TODO: consider doing this unconditionally, since that
170 # might allow merging between repositories created with darcs-to-git
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
171 fill_from_darcs_hash_comments
172 end
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
173 end
174
175 def record_git_commit(commit_id, identifier)
176 # using one file per darcs patch would be an incredible waste of space
177 # on my system one file takes up 4K even if only a few bytes are in it
178 # hence we just use a simple YAML hash
179 @darcs_patches_in_git[identifier] = commit_id
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
180 File.open(@patch_file_name, 'w') do |f|
181 YAML.dump(@darcs_patches_in_git, f)
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
182 end
183 end
184
185 def find_git_commit(is_tag, git_tag_name, identifier)
c6a1881 @purcell Use a more reliable trick to determine if the git repo is empty
authored May 12, 2008
186 return nil if empty_repo?
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
187 if is_tag
6c83a4e Prevent error when copying first darcs 2 tag to git 1.6 repo
Suraj N. Kurapati authored Sep 21, 2008
188 (output_of("git", "tag", "-l") rescue "").split(/\r?\n/).include?(git_tag_name) &&
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
189 output_of("git", "rev-list", "--max-count=1", "tags/#{git_tag_name}").strip
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
190 else
191 @darcs_patches_in_git[identifier];
192 end
193 end
c6a1881 @purcell Use a more reliable trick to determine if the git repo is empty
authored May 12, 2008
194
195 private
196
197 def empty_repo?
198 !system("git rev-parse --verify HEAD >/dev/null 2>&1")
199 end
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
200
201 def fill_from_darcs_hash_comments
202 return if empty_repo?
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
203 Array(output_of("git", "log", "--grep=darcs-hash:").split(/^commit /m)[1..-1]).each do |entry|
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
204 commit_id, identifier = entry.scan(/^([a-z0-9]+$).*darcs-hash:(.*?)$/sm).flatten
205 record_git_commit(commit_id, identifier)
206 end
207 end
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
208 end
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
209
210 # -------------------------------------------------------------------------------
211 # Reading darcs patches and applying them to a git repo
212 # -------------------------------------------------------------------------------
213
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
214 class DarcsPatch
9685ea2 @purcell Include patch comment as well as just name (thanks Antti-Juhani Kaija…
authored Oct 28, 2007
215 attr_accessor :source_repo, :author, :date, :inverted, :identifier, :name, :is_tag, :git_tag_name, :comment
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
216 attr_reader :git_author_name, :git_author_email
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
217
218 def initialize(source_repo, patch_xml)
219 self.source_repo = source_repo
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
220 self.author = patch_xml.attribute('author').value.darcs_unescape
c547c01 @nominolo Proper handling of timezones
nominolo authored May 7, 2008
221 self.date = darcs_date_to_git_date(patch_xml.attribute('date').value,
222 patch_xml.attribute('local_date').value)
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
223 self.inverted = (patch_xml.attribute('inverted').to_s == 'True')
224 self.identifier = patch_xml.attribute('hash').to_s
bd442b4 @purcell Move DarcsPatch#decode_darcs_escape to String#darcs_unescape
authored May 10, 2008
225 self.name = patch_xml.get_elements('name').first.get_text.value.darcs_unescape rescue 'Unnamed patch'
226 self.comment = patch_xml.get_elements('comment').first.get_text.value.darcs_unescape rescue nil
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
227 if (self.is_tag = (self.name =~ /^TAG (.*)/))
228 self.git_tag_name = $1.gsub(/[\s:]+/, '_')
229 end
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
230 @git_author_name, @git_author_email = AUTHOR_MAP[author]
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
231 end
232
233 def <=>(other)
234 self.identifier <=> other.identifier
235 end
236
237 def git_commit_message
de433de @purcell Add -h/--help switches (requested by Brenda Wallace)
authored Feb 17, 2008
238 [ ((inverted ? "UNDO: #{name}" : name) unless name =~ /^\[\w+ @ \d+\]/),
ae775b5 @purcell Return to storing darcs-hash in commit comments, but provide an optio…
authored May 12, 2008
239 comment,
240 ("darcs-hash:#{identifier}" unless OPTIONS[:clean_commit_messages])
c213d24 @nominolo Move darcs hashes out of commit messages. By default they now go into
nominolo authored May 7, 2008
241 ].compact.join("\n\n")
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
242 end
243
244 def self.read_from_repo(repo)
7220bb8 @nominolo Cosmetics
nominolo authored May 9, 2008
245 REXML::Document.new(output_of("darcs", "changes", "--reverse",
246 "--repodir=#{repo}", "--xml",
247 "--summary")).
248 get_elements('changelog/patch').map do |p|
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
249 DarcsPatch.new(repo, p)
250 end
251 end
252
253 # Return committish for corresponding patch in current git repo, or false/nil
254 def id_in_git_repo
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
255 @git_commit ||= COMMIT_HISTORY.find_git_commit(is_tag, git_tag_name, identifier)
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
256 end
257
258 def pull_and_apply
259 puts "\n" + ("=" * 80)
f76d7f2 Better handling for darcs changeset authors in rfc822 format ("blah <…
Steve authored Oct 17, 2007
260 puts "PATCH : #{name}"
261 puts "DATE : #{date}"
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
262 puts "AUTHOR: #{author} => #{git_author_name} <#{git_author_email}>"
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
263 puts "=" * 80
264
265 if id_in_git_repo
5eb2249 Fix broken logging message
Steve authored Sep 17, 2007
266 puts "Already imported to git as #{id_in_git_repo}"
267 return
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
268 end
269
270 pull
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
271 system("git", "status")
6d8c857 @purcell Check that darcs reports the working area as clean before pulling the…
authored May 12, 2008
272 commit_to_git_repo
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
273 end
274
275 private
276
277 def pull
6d8c857 @purcell Check that darcs reports the working area as clean before pulling the…
authored May 12, 2008
278 unless darcs_reports_clean_repo?
279 raise "Darcs reports dirty repo before pulling #{identifier}; confused, so aborting"
280 end
7220bb8 @nominolo Cosmetics
nominolo authored May 9, 2008
281 run("darcs", "pull", "--all", "--quiet",
282 "--match", "hash #{identifier}",
283 "--set-scripts-executable", source_repo)
6d8c857 @purcell Check that darcs reports the working area as clean before pulling the…
authored May 12, 2008
284 unless darcs_reports_clean_repo?
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
285 puts "Darcs reports dirty directory: assuming conflict that is fixed by a later patch... reverting"
286 run("darcs revert --all")
8f41333 @smcv Run rm in a more cross-platform way
smcv authored Jul 17, 2008
287 run("find . -name '*-darcs-backup0'|xargs rm -f") # darcs2 creates these
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
288 end
39f0e06 @smcv Fix repository cleanup after pull
smcv authored Jul 10, 2008
289 unless darcs_reports_clean_repo?
290 system("darcs whatsnew -sl")
291 raise "Failed to clean repo, see above"
292 end
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
293 end
294
6d8c857 @purcell Check that darcs reports the working area as clean before pulling the…
authored May 12, 2008
295 def darcs_reports_clean_repo?
39f0e06 @smcv Fix repository cleanup after pull
smcv authored Jul 10, 2008
296 `darcs whatsnew -sl | egrep -v '^a (\./)?\.git(/|$)'` =~ /^(No changes!)?$/
6d8c857 @purcell Check that darcs reports the working area as clean before pulling the…
authored May 12, 2008
297 end
298
299 def commit_to_git_repo
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
300 ENV['GIT_AUTHOR_NAME'] = ENV['GIT_COMMITTER_NAME'] = git_author_name
301 ENV['GIT_AUTHOR_EMAIL'] = ENV['GIT_COMMITTER_EMAIL'] = git_author_email
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
302 ENV['GIT_AUTHOR_DATE'] = ENV['GIT_COMMITTER_DATE'] = date
303 if is_tag
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
304 run("git", "tag", "-a", "-m", git_commit_message, git_tag_name)
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
305 else
306 if (new_files = git_new_files).any?
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
307 run(*(["git", "add"] + new_files))
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
308 end
4f630f3 @purcell Improved parsing of git-ls-files output, which changed with a git rel…
authored Oct 27, 2007
309 if git_changed_files.any? || new_files.any?
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
310 run("git", "commit", "-a", "-m", git_commit_message)
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
311 end
0571c80 @nominolo Unconditionally record commit id for darcs patch.
nominolo authored May 9, 2008
312 # get full id of last commit and associate it with the patch id
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
313 commit_id = output_of("git", "log", "-n1").scan(/^commit ([a-z0-9]+$)/).flatten.first
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
314 COMMIT_HISTORY.record_git_commit(commit_id, identifier)
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
315 end
316 end
317
c547c01 @nominolo Proper handling of timezones
nominolo authored May 7, 2008
318 def darcs_date_to_git_date(utc,local)
7a488be @nominolo Improve documentation for timezone extraction
nominolo authored May 9, 2008
319 # Calculates a git-friendly date (e.g., timezone CET decribed as
320 # +0100) by using the two date fields that darcs gives us: a list
321 # of numbers describing the UTC time and a local time formatted in
322 # a human-readable format. We could parse the local time and
323 # derive the timezone offset from the timezone name. but timezones
324 # aren't well-defined, so we ignore the timezone name and instead
325 # calculate the timezone offset ourselves by calculating the
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
326 # difference between local time and UTC time.
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
327 if not utc =~ /^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/
c547c01 @nominolo Proper handling of timezones
nominolo authored May 7, 2008
328 raise "Wrong darcs date format"
329 end
330 utc_time = Time.utc($1,$2,$3,$4,$5,$6)
7a488be @nominolo Improve documentation for timezone extraction
nominolo authored May 9, 2008
331 # example: Mon Oct 2 14:23:28 CEST 2006
332 # everything except timezone name is fixed-length, if parsing
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
333 # fails we just use UTC
7a488be @nominolo Improve documentation for timezone extraction
nominolo authored May 9, 2008
334 pat = /^\w\w\w (\w\w\w) ([ 1-9]\d) ([ 0-9]\d)\:(\d\d)\:(\d\d) \w* (\d\d\d\d)/
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
335 local_time = if pat =~ local
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
336 Time.utc($6,$1,$2,$3,$4,$5)
337 else
338 utc_time
339 end
7a488be @nominolo Improve documentation for timezone extraction
nominolo authored May 9, 2008
340 offs = local_time - utc_time # time offset in seconds
c547c01 @nominolo Proper handling of timezones
nominolo authored May 7, 2008
341 t = local_time
7a488be @nominolo Improve documentation for timezone extraction
nominolo authored May 9, 2008
342 # formats the above example as: 2006-10-02 14:23:28 +0200
343 s = sprintf("%4d-%02d-%02d %02d:%02d:%02d %s%02d%02d",
344 t.year, t.month, t.day,
c547c01 @nominolo Proper handling of timezones
nominolo authored May 7, 2008
345 t.hour, t.min, t.sec,
7a488be @nominolo Improve documentation for timezone extraction
nominolo authored May 9, 2008
346 offs < 0 ? "-" : "+", offs.abs/3600, offs.abs.modulo(3600)/60 )
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
347 end
348
4f630f3 @purcell Improved parsing of git-ls-files output, which changed with a git rel…
authored Oct 27, 2007
349 def git_ls_files(wanted)
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
350 output_of(*["git", "ls-files", "-t", "-o", "-m", "-d", "-z", "-X", ".git/info/exclude"]).scan(/(.?) (.*?)\0/m).map do |code, name|
4f630f3 @purcell Improved parsing of git-ls-files output, which changed with a git rel…
authored Oct 27, 2007
351 name if wanted.include?(code)
352 end.compact
353 end
354 def git_new_files() git_ls_files(["?"]) end
355 def git_changed_files() git_ls_files(%w(? R C)) end
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
356 end
357
76cbfc2 @nominolo Allow listing of authors
nominolo authored May 9, 2008
358 def extract_authors(patches)
359 unique_authors = {}
360 patches.each do |p|
361 unique_authors[p.author] =
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
362 "#{p.git_author_name}" + (p.git_author_email.nil? ? "" : " <#{p.git_author_email}>")
76cbfc2 @nominolo Allow listing of authors
nominolo authored May 9, 2008
363 end
364 puts "# You can use the following output as a starting point for an author_map"
365 puts "# Just fill in the proper text after the colon; put email addresses in"
366 puts "# angle brackets. You can remove any lines that look OK to you."
367 # TODO: Can we make the output sorted?
368 puts YAML::dump( unique_authors )
369 end
370
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
371
372 # -------------------------------------------------------------------------------
373 # Pre-flight checks
374 # -------------------------------------------------------------------------------
375
11ffabe @purcell Properly initialise conversion repo when converting old-format darcs …
authored Nov 22, 2008
376 DARCS_VERSION = output_of(*%w(darcs -v)).scan(/(\d+)\.(\d+)\.(\d+)/).flatten.map {|v| v.to_i}
b88ae01 Add support for darcs2 repositories.
Suraj N. Kurapati authored Sep 21, 2008
377
378 def darcs2_repo?(repo)
379 begin
11ffabe @purcell Properly initialise conversion repo when converting old-format darcs …
authored Nov 22, 2008
380 output_of("darcs", "show", "repo", "--repodir=#{repo}") =~ /Format:.*darcs-2/
b88ae01 Add support for darcs2 repositories.
Suraj N. Kurapati authored Sep 22, 2008
381 rescue # darcs1 does not have a "show" command, so we get an exception
11ffabe @purcell Properly initialise conversion repo when converting old-format darcs …
authored Nov 22, 2008
382 false
b88ae01 Add support for darcs2 repositories.
Suraj N. Kurapati authored Sep 22, 2008
383 end
384 end
385
4cce98f @purcell Add darcs version check and warning, due to known issues with darcs 1…
authored Feb 22, 2008
386 class Array; include Comparable; end
387
11ffabe @purcell Properly initialise conversion repo when converting old-format darcs …
authored Nov 22, 2008
388 unless DARCS_VERSION > [1, 0, 7]
4cce98f @purcell Add darcs version check and warning, due to known issues with darcs 1…
authored Feb 22, 2008
389 STDERR.write("WARNING: your darcs appears to be old, and may not work with this script\n")
390 end
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
391
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
392
393 # -------------------------------------------------------------------------------
394 # Initialise the working area
395 # -------------------------------------------------------------------------------
bf4f1ba @purcell Set PAGER / GIT_PAGER to 'cat' globally (thanks Samium Gromoff)
authored Nov 22, 2008
396 ENV['GIT_PAGER'] = ENV['PAGER'] = "cat" # so that pager of git-log doesn't halt conversion
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
397
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
398 unless File.directory?("_darcs")
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
399 puts "Initialising the working area."
b88ae01 Add support for darcs2 repositories.
Suraj N. Kurapati authored Sep 22, 2008
400
401 darcs_init = %w(darcs init)
11ffabe @purcell Properly initialise conversion repo when converting old-format darcs …
authored Nov 22, 2008
402 if darcs2_repo?(SRCREPO)
403 darcs_init << "--darcs-2"
404 elsif DARCS_VERSION >= [2, 0, 0]
405 darcs_init << "--old-fashioned-inventory"
406 end
b88ae01 Add support for darcs2 repositories.
Suraj N. Kurapati authored Sep 22, 2008
407 run(*darcs_init)
408
38d026d @purcell Use "git subcommand" rather than "git-subcommand", for git 1.6 compat…
authored Aug 25, 2008
409 run("git", "init")
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
410 File.open(".git/info/exclude", "a") { |f| f.write("_darcs\n.DS_Store\n") }
411 File.open("_darcs/prefs/boring", "a") { |f| f.write("\\.git$\n\\.DS_Store$\n") }
7f35b89 @nominolo Add TODO
nominolo authored May 9, 2008
412 # TODO: migrate darcs borings into git excludes?
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
413 end
414
3de3836 @purcell Smoothly convert existing "darcs-hash:" metadata into the new-style Y…
authored May 12, 2008
415
416 COMMIT_HISTORY = CommitHistory.new(GIT_PATCHES)
417
87433cc Initial version, working for single-branch imports with tags
Steve authored Sep 12, 2007
418
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
419 AUTHOR_MAP = if OPTIONS[:author_map]
0bfb333 @purcell Some tidyup work, particularly regarding author maps
authored May 10, 2008
420 AuthorMap.load(OPTIONS[:author_map])
421 elsif File.exists?(DEFAULT_AUTHOR_MAP_FILE)
422 AuthorMap.load(DEFAULT_AUTHOR_MAP_FILE)
423 else
424 AuthorMap.new
425 end
426 AUTHOR_MAP.default_email = OPTIONS[:default_email]
ca12ee3 @nominolo Remember author substitition map
nominolo authored May 9, 2008
427
c8bfc11 @purcell Replace $darcs_patches_in_git with CommitHistory class
authored May 11, 2008
428
38670d8 Support incremental pulling when some old patches were no-ops (e.g. e…
Steve authored Sep 17, 2007
429 patches = DarcsPatch.read_from_repo(SRCREPO)
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
430 if OPTIONS[:list_authors]
76cbfc2 @nominolo Allow listing of authors
nominolo authored May 9, 2008
431 extract_authors(patches)
432 exit(0)
433 end
38670d8 Support incremental pulling when some old patches were no-ops (e.g. e…
Steve authored Sep 17, 2007
434
f5bf94d @purcell Clean up logic linking --patches option and running of post-flight co…
authored May 12, 2008
435 patches_available = []
38670d8 Support incremental pulling when some old patches were no-ops (e.g. e…
Steve authored Sep 17, 2007
436 while patch = patches.pop
d596b35 @nominolo Don't abort if we find a patch we already have
nominolo authored May 9, 2008
437 next if patch.id_in_git_repo
f5bf94d @purcell Clean up logic linking --patches option and running of post-flight co…
authored May 12, 2008
438 patches_available.unshift(patch)
38670d8 Support incremental pulling when some old patches were no-ops (e.g. e…
Steve authored Sep 17, 2007
439 end
440
f5bf94d @purcell Clean up logic linking --patches option and running of post-flight co…
authored May 12, 2008
441 patches_to_pull = if OPTIONS[:num_patches]
442 patches_available.first(OPTIONS[:num_patches])
443 else
444 patches_available
445 end
abbefc5 @nominolo Allow limiting the number of patches to pull
nominolo authored May 9, 2008
446
a110c04 @purcell Provide and use Symbol#to_proc
authored May 11, 2008
447 patches_to_pull.each &:pull_and_apply
a1fe601 @nominolo Hint at the usefulness of 'git gc'
nominolo authored May 7, 2008
448
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
449 pulled = patches_to_pull.size
450 if pulled == 0
451 puts "\nNothing to pull."
452 else
453 puts "\nPulled #{pulled} patch#{"es" unless pulled == 1}."
454 puts "\nDarcs import successful! You may now want to run `git gc' to
a1fe601 @nominolo Hint at the usefulness of 'git gc'
nominolo authored May 7, 2008
455 improve space usage the git repo"
a6b9f7e @nominolo Add consistency check after import.
nominolo authored May 7, 2008
456 end
457
f5bf94d @purcell Clean up logic linking --patches option and running of post-flight co…
authored May 12, 2008
458
459 # -------------------------------------------------------------------------------
460 # Post-flight checks
461 # -------------------------------------------------------------------------------
462
463 # if we didn't pull all patches, then the consistency check would
464 # fail, so we simply skip it
465 if patches_to_pull.size == patches_available.size
ffd9c8d @purcell Tidy up consistency check code, and fix some unidiomatic constructions
authored May 12, 2008
466 puts "Comparing final state with source repo..."
467 system("diff", "-ur", "-x", "_darcs", "-x", ".git", ".", SRCREPO)
468 if $? != 0
469 abort <<-end_msg
470 !!! There were differences! See diff above for details.
471 !!! It may be that the source repository was dirty.
472 !!! Run "cd #{SRCREPO} && darcs whatsnew -sl" to check.
473 end_msg
474 end
475 end
Something went wrong with that request. Please try again.