command :resolve do |c| c.workflow :hg c.desc "Retry file merges, or mark files as successfully hand-merged" c.opt :all, "Attempt to resolve (or mark) all unresolved files", :short => "-a" c.opt :list, "List unresolved files", :short => "-l" c.opt :mark, "Mark file(s) as resolved", :short => "-m" c.opt :unmark, "Mark file(s) as unresolved", :short => "-u" c.opt :include, "Specify patterns of files to include in the operation", :short => "-I", :type => :string c.opt :exclude, "Specify patterns of files to exclude in the operation", :short => "-E", :type => :string c.before do |opts, args| parse_args = lambda {|os| [:all, :mark, :unmark, :list].map {|i| os[i] } } # Checks to make sure user input is valid all, mark, unmark, list = *parse_args[ opts ] if (list && (mark || unmark)) || (mark && unmark) raise abort("too many options specified") end if all && (opts[:include] || opts[:exclude] || args.any?) raise abort("can't specify --all and patterns or files") end if !(all || args.any? || opts[:include] || opts[:exclude] || mark || unmark || list) raise abort("no files or directories specified; use --all to remerge all files") end true end c.on_run do |opts, args| repo = opts[:repository] parse_args = lambda {|os| [:all, :mark, :unmark, :list].map {|i| os[i] } } all, mark, unmark, list = *parse_args[opts] merge_state = Amp::Merges::MergeState.new(repo) if opts[:all] # the block means "default to true" - so basically ignore all other input match = Amp::Match.create(:files => []) { true } else # the block means "default to false" - rely entirely on user input match = Amp::Match.create(:includer => opts[:include], :excluder => opts[:exclude], :files => args) { false } end # iterate over each entry in the merge state file merge_state.each do |file, status| # check to see if our user wants this file if match.call(file) if list Amp::UI.say "#{status.first} #{file}" elsif mark # the "r" means resolved merge_state.mark(file, "r") Amp::UI.say "#{file} marked as #{"resolved".blue}" elsif unmark # the "u" means unresolved merge_state.mark(file, "u") Amp::UI.say "#{file} marked as #{"unresolved".red}" else # retry the merge working_changeset = repo[nil] merge_changeset = working_changeset.parents.last # backup the current file to a .resolve file (but retain the extension # so editors that rely on extensions won't bug out) path = repo.working_join file File.copy(path, path + ".resolve" + File.extname(path)) # try to merge the files! merge_state.resolve(file, working_changeset, merge_changeset) # restore the backup to .orig (overwriting the old one) File.move(path + ".resolve" + File.extname(path), path + ".orig" + File.extname(path)) end end end end end