lib/rim/upload_module_helper.rb in esr-rim-1.4.0 vs lib/rim/upload_module_helper.rb in esr-rim-1.4.2

- old
+ new

@@ -1,162 +1,163 @@ -require 'rim/module_helper' -require 'rim/rim_info' -require 'rim/file_helper' -require 'rim/dirty_check' -require 'rim/status_builder' -require 'tempfile' - -module RIM - -class UploadModuleHelper < ModuleHelper - - def initialize(workspace_root, module_info, review, logger) - super(workspace_root, module_info, logger) - @review = review - end - - # do the module uploads for revisions given by sha - def upload(parent, sha1s) - upload_module_changes(parent, sha1s) - end - -private - - # upload the content of the module - def upload_module_changes(parent_sha1, sha1s) - remote_path = fetch_module - # search for the first revision that is not - tmp_git_path = clone_or_fetch_repository(remote_path, module_tmp_git_path(@remote_path)) - RIM::git_session(tmp_git_path) do |dest| - local_branch = nil - remote_branch = nil - infos = nil - if @module_info.subdir - dest_path = File.join([tmp_git_path] + @module_info.subdir.split("/")) - else - dest_path = tmp_git_path - end - RIM::git_session(@ws_root) do |src| - infos = get_branches_and_revision_infos(src, dest, parent_sha1, sha1s) - if infos.branches.size == 1 - remote_branch = infos.branches[0] - if dest.has_remote_branch?(remote_branch) - infos.rev_infos.each do |rev_info| - local_branch = create_update_branch(dest, infos.parent_sha1, rev_info.src_sha1) if !local_branch - copy_revision_files( - src, - rev_info.src_sha1, - dest_path, - rev_info.rim_info.ignores - ) - commit_changes(dest, local_branch, rev_info.src_sha1, rev_info.message) - end - else - raise RimException.new("The target revision '#{@module_info.target_revision}' of module #{@module_info.local_path} is not a branch. No push can be performed.") - end - elsif infos.branches.size > 1 - raise RimException.new("There are commits for module #{@module_info.local_path} on multiple target revisions (#{infos.branches.join(", ")}).") - end - end - # Finally we're done. Push the changes - if local_branch && dest.rev_sha1(local_branch) != infos.parent_sha1 - push_branch = @review && @module_info.remote_branch_format && !@module_info.remote_branch_format.empty? \ - ? @module_info.remote_branch_format % remote_branch : remote_branch - dest.execute("git push #{@remote_url} #{local_branch}:#{push_branch}") - dest.execute("git checkout --detach #{local_branch}") - dest.execute("git branch -D #{local_branch}") - @logger.info("Commited changes for module #{@module_info.local_path} to remote branch #{push_branch}.") - else - @logger.info("No changes to module #{@module_info.local_path}.") - end - end - end - - # search backwards for all revision infos - def get_branches_and_revision_infos(src_session, dest_session, parent_sha1, sha1s) - infos = [] - branches = [] - dest_parent_sha1 = nil - (sha1s.size() - 1).step(0, -1) do |i| - info = get_revision_info(src_session, dest_session, sha1s[i]) - if !info.dest_sha1 && info.rim_info.target_revision - infos.unshift(info) - branches.push(info.rim_info.target_revision) if !branches.include?(info.rim_info.target_revision) - else - dest_parent_sha1 = info.dest_sha1 - break - end - end - dest_parent_sha1 = get_riminfo_for_revision(src_session, parent_sha1).revision_sha1 if !dest_parent_sha1 - dest_parent_sha1 = infos.first.rim_info.revision_sha1 if !dest_parent_sha1 && !infos.empty? - return Struct.new(:branches, :parent_sha1, :rev_infos).new(branches, dest_parent_sha1, infos) - end - - RevisionInfo = Struct.new(:dest_sha1, :src_sha1, :rim_info, :message) - - # collect infos for a revision - def get_revision_info(src_session, dest_session, src_sha1) - module_status = StatusBuilder.new.rev_module_status(src_session, src_sha1, @module_info.local_path) - rim_info = get_riminfo_for_revision(src_session, src_sha1) - dest_sha1 = dest_session.rev_sha1("rim-#{src_sha1}") - msg = src_session.execute("git show -s --format=%B #{src_sha1}") - RevisionInfo.new(module_status && module_status.dirty? ? dest_sha1 : rim_info.revision_sha1, src_sha1, rim_info, msg) - end - - # commit changes to session - def commit_changes(session, branch, sha1, msg) - if session.status.lines.any? - # add before commit because the path can be below a not yet added path - session.execute("git add --all") - msg_file = Tempfile.new('message') - begin - msg_file << msg - msg_file.close - session.execute("git commit -F #{msg_file.path}") - ensure - msg_file.close(true) - end - # create tag - session.execute("git tag rim-#{sha1} refs/heads/#{branch}") - end - end - - # get target revision for this module for workspace revision - def get_riminfo_for_revision(session, sha1) - session.execute("git show #{sha1}:#{File.join(@module_info.local_path, RimInfo::InfoFileName)}") do |out, e| - return RimInfo.from_s(!e ? out : "") - end - end - - # create update branch for given revision - def create_update_branch(session, dest_sha1, src_sha1) - branch = "rim/#{src_sha1}" - session.execute("git checkout -B #{branch} #{dest_sha1}") - branch - end - - # copy files from given source revision into destination dir - def copy_revision_files(src_session, src_sha1, dest_dir, ignores) - Dir.mktmpdir do |tmp_dir| - src_session.execute("git archive --format tar #{src_sha1} #{@module_info.local_path} | tar -x -C #{tmp_dir}") - tmp_module_dir = File.join(tmp_dir, @module_info.local_path) - files = FileHelper.find_matching_files(tmp_module_dir, false, "/**/*", File::FNM_DOTMATCH) - files.delete(".") - files.delete("..") - files.delete(RimInfo::InfoFileName) - files -= FileHelper.find_matching_files(tmp_module_dir, false, ignores) - # have source files now. Now clear destination folder and copy - prepare_empty_folder(dest_dir, ".git/**/*") - files.each do |f| - src_path = File.join(tmp_module_dir, f) - if File.file?(src_path) - path = File.join(dest_dir, f) - FileUtils.mkdir_p(File.dirname(path)) - FileUtils.cp(src_path, path) - end - end - end - end - -end - -end +require 'rim/module_helper' +require 'rim/rim_info' +require 'rim/file_helper' +require 'rim/dirty_check' +require 'rim/status_builder' +require 'tempfile' + +module RIM + +class UploadModuleHelper < ModuleHelper + + def initialize(workspace_root, module_info, review, logger) + super(workspace_root, module_info, logger) + @review = review + end + + # do the module uploads for revisions given by sha + def upload(parent, sha1s) + upload_module_changes(parent, sha1s) + end + +private + + # upload the content of the module + def upload_module_changes(parent_sha1, sha1s) + remote_path = fetch_module + # search for the first revision that is not + tmp_git_path = clone_or_fetch_repository(remote_path, module_tmp_git_path(@remote_path)) + RIM::git_session(tmp_git_path) do |dest| + local_branch = nil + remote_branch = nil + infos = nil + if @module_info.subdir + dest_path = File.join([tmp_git_path] + @module_info.subdir.split("/")) + else + dest_path = tmp_git_path + end + RIM::git_session(@ws_root) do |src| + infos = get_branches_and_revision_infos(src, dest, parent_sha1, sha1s) + if infos.branches.size == 1 + remote_branch = infos.branches[0] + if dest.has_remote_branch?(remote_branch) + infos.rev_infos.each do |rev_info| + local_branch = create_update_branch(dest, infos.parent_sha1, rev_info.src_sha1) if !local_branch + copy_revision_files( + src, + rev_info.src_sha1, + dest_path, + rev_info.rim_info.ignores + ) + commit_changes(dest, local_branch, rev_info.src_sha1, rev_info.message) + end + else + raise RimException.new("The target revision '#{@module_info.target_revision}' of module #{@module_info.local_path} is not a branch. No push can be performed.") + end + elsif infos.branches.size > 1 + raise RimException.new("There are commits for module #{@module_info.local_path} on multiple target revisions (#{infos.branches.join(", ")}).") + end + end + # Finally we're done. Push the changes + if local_branch && dest.rev_sha1(local_branch) != infos.parent_sha1 + push_branch = @review && @module_info.remote_branch_format && !@module_info.remote_branch_format.empty? \ + ? @module_info.remote_branch_format % remote_branch : remote_branch + dest.execute("git push #{@remote_url} #{local_branch}:#{push_branch}") + dest.execute("git checkout --detach #{local_branch}") + dest.execute("git branch -D #{local_branch}") + @logger.info("Commited changes for module #{@module_info.local_path} to remote branch #{push_branch}.") + else + @logger.info("No changes to module #{@module_info.local_path}.") + end + end + end + + # search backwards for all revision infos + def get_branches_and_revision_infos(src_session, dest_session, parent_sha1, sha1s) + infos = [] + branches = [] + dest_parent_sha1 = nil + (sha1s.size() - 1).step(0, -1) do |i| + info = get_revision_info(src_session, dest_session, sha1s[i]) + if !info.dest_sha1 && info.rim_info.target_revision + infos.unshift(info) + branches.push(info.rim_info.target_revision) if !branches.include?(info.rim_info.target_revision) + else + dest_parent_sha1 = info.dest_sha1 + break + end + end + dest_parent_sha1 = get_riminfo_for_revision(src_session, parent_sha1).revision_sha1 if !dest_parent_sha1 + dest_parent_sha1 = infos.first.rim_info.revision_sha1 if !dest_parent_sha1 && !infos.empty? + return Struct.new(:branches, :parent_sha1, :rev_infos).new(branches, dest_parent_sha1, infos) + end + + RevisionInfo = Struct.new(:dest_sha1, :src_sha1, :rim_info, :message) + + # collect infos for a revision + def get_revision_info(src_session, dest_session, src_sha1) + module_status = StatusBuilder.new.rev_module_status(src_session, src_sha1, @module_info.local_path) + rim_info = get_riminfo_for_revision(src_session, src_sha1) + dest_sha1 = dest_session.rev_sha1("rim-#{src_sha1}") + msg = src_session.execute("git show -s --format=%B #{src_sha1}") + RevisionInfo.new(module_status && module_status.dirty? ? dest_sha1 : rim_info.revision_sha1, src_sha1, rim_info, msg) + end + + # commit changes to session + def commit_changes(session, branch, sha1, msg) + if session.status.lines.any? + # add before commit because the path can be below a not yet added path + session.execute("git add --all") + msg_file = Tempfile.new('message') + begin + msg_file << msg + msg_file.close + session.execute("git commit -F #{msg_file.path}") + ensure + msg_file.close(true) + end + # create tag + session.execute("git tag rim-#{sha1} refs/heads/#{branch}") + end + end + + # get target revision for this module for workspace revision + def get_riminfo_for_revision(session, sha1) + session.execute("git show #{sha1}:#{File.join(@module_info.local_path, RimInfo::InfoFileName)}") do |out, e| + return RimInfo.from_s(!e ? out : "") + end + end + + # create update branch for given revision + def create_update_branch(session, dest_sha1, src_sha1) + branch = "rim/#{src_sha1}" + session.execute("git checkout -B #{branch} #{dest_sha1}") + branch + end + + # copy files from given source revision into destination dir + def copy_revision_files(src_session, src_sha1, dest_dir, ignores) + Dir.mktmpdir do |tmp_dir| + tmp_dir = Dir.glob(tmp_dir)[0] + src_session.execute("git archive --format tar #{src_sha1} #{@module_info.local_path} | tar -C #{tmp_dir} -xf -") + tmp_module_dir = File.join(tmp_dir, @module_info.local_path) + files = FileHelper.find_matching_files(tmp_module_dir, false, "/**/*", File::FNM_DOTMATCH) + files.delete(".") + files.delete("..") + files.delete(RimInfo::InfoFileName) + files -= FileHelper.find_matching_files(tmp_module_dir, false, ignores) + # have source files now. Now clear destination folder and copy + prepare_empty_folder(dest_dir, ".git/**/*") + files.each do |f| + src_path = File.join(tmp_module_dir, f) + if File.file?(src_path) + path = File.join(dest_dir, f) + FileUtils.mkdir_p(File.dirname(path)) + FileUtils.cp(src_path, path) + end + end + end + end + +end + +end