Class | RSCM::Cvs |
In: |
lib/rscm/scm/cvs.rb
|
Parent: | Base |
RSCM implementation for CVS.
You need a cvs executable on the PATH in order for it to work.
NOTE: On Cygwin this has to be the win32 build of cvs and not the Cygwin one.
branch | [RW] | |
mod | [RW] | |
password | [RW] | |
root | [RW] |
# File lib/rscm/scm/cvs.rb, line 20 20: def initialize(root=nil, mod=nil, branch=nil, password=nil) 21: @root, @mod, @branch, @password = root, mod, branch, password 22: end
# File lib/rscm/scm/cvs.rb, line 29 29: def add(relative_filename) 30: cvs(@checkout_dir, "add #{relative_filename}") 31: end
# File lib/rscm/scm/cvs.rb, line 140 140: def apply_label(label) 141: cvs(@checkout_dir, "tag -c #{label}") 142: end
# File lib/rscm/scm/cvs.rb, line 230 230: def can_create_central? 231: begin 232: local? 233: rescue 234: false 235: end 236: end
# File lib/rscm/scm/cvs.rb, line 221 221: def central_exists? 222: if(local?) 223: File.exists?("#{path}/CVSROOT/loginfo") 224: else 225: # don't know. assume yes. 226: true 227: end 228: end
# File lib/rscm/scm/cvs.rb, line 242 242: def checked_out? 243: rootcvs = File.expand_path("#{checkout_dir}/CVS/Root") 244: File.exists?(rootcvs) 245: end
The extra simulate parameter is not in accordance with the AbstractSCM API, but it‘s optional and is only being used from within this class (uptodate? method).
# File lib/rscm/scm/cvs.rb, line 42 42: def checkout(to_identifier=nil, simulate=false) 43: checked_out_files = [] 44: if(checked_out?) 45: path_regex = /^[U|P] (.*)/ 46: cvs(@checkout_dir, update_command(to_identifier), simulate) do |line| 47: if(line =~ path_regex) 48: path = $1.chomp 49: yield path if block_given? 50: checked_out_files << path 51: end 52: end 53: else 54: prefix = File.basename(@checkout_dir) 55: path_regex = /^[U|P] #{prefix}\/(.*)/ 56: # This is a workaround for the fact that -d . doesn't work - must be an existing sub folder. 57: FileUtils.mkdir_p(@checkout_dir) unless File.exist?(@checkout_dir) 58: target_dir = File.basename(@checkout_dir) 59: run_checkout_command_dir = File.dirname(@checkout_dir) 60: # -D is sticky, but subsequent updates will reset stickiness with -A 61: cvs(run_checkout_command_dir, checkout_command(target_dir, to_identifier), simulate) do |line| 62: if(line =~ path_regex) 63: path = $1.chomp 64: yield path if block_given? 65: checked_out_files << path 66: end 67: end 68: end 69: checked_out_files 70: end
# File lib/rscm/scm/cvs.rb, line 72 72: def commit(message) 73: cvs(@checkout_dir, commit_command(message)) 74: end
# File lib/rscm/scm/cvs.rb, line 207 207: def create_central 208: raise "Can't create central CVS repository for #{root}" unless can_create_central? 209: File.mkpath(path) 210: cvs(path, "init") 211: end
# File lib/rscm/scm/cvs.rb, line 213 213: def destroy_central 214: if(File.exist?(path) && local?) 215: FileUtils.rm_rf(path) 216: else 217: raise "Cannot destroy central repository. '#{path}' doesn't exist or central repo isn't local to this machine" 218: end 219: end
# File lib/rscm/scm/cvs.rb, line 91 91: def diff(revision_file) 92: with_working_dir(@checkout_dir) do 93: opts = case revision_file.status 94: when /#{RevisionFile::MODIFIED}/; "#{revision_option(revision_file.previous_native_revision_identifier)} #{revision_option(revision_file.native_revision_identifier)}" 95: when /#{RevisionFile::DELETED}/; "#{revision_option(revision_file.previous_native_revision_identifier)}" 96: when /#{RevisionFile::ADDED}/; "#{revision_option(Time.epoch)} #{revision_option(revision_file.native_revision_identifier)}" 97: end 98: # IMPORTANT! CVS NT has a bug in the -N diff option 99: # http://www.cvsnt.org/pipermail/cvsnt-bugs/2004-November/000786.html 100: cmd = command_line("diff -Nu #{opts} #{revision_file.path}") 101: Better.popen(cmd, "r", 1) do |io| 102: return(yield(io)) 103: end 104: end 105: end
# File lib/rscm/scm/cvs.rb, line 24 24: def import_central(dir, message) 25: modname = File.basename(dir) 26: cvs(dir, "import -m \"#{message}\" #{modname} VENDOR START") 27: end
# File lib/rscm/scm/cvs.rb, line 172 172: def install_trigger(trigger_command, trigger_files_checkout_dir) 173: raise "mod can't be null or empty" if (mod.nil? || mod == "") 174: 175: root_cvs = create_root_cvs(trigger_files_checkout_dir) 176: root_cvs.checkout 177: with_working_dir(trigger_files_checkout_dir) do 178: trigger_line = "#{mod} #{trigger_command}\n" 179: File.open("loginfo", File::WRONLY | File::APPEND) do |file| 180: file.puts(trigger_line) 181: end 182: begin 183: root_cvs.commit("Installed trigger for CVS module '#{mod}'") 184: rescue 185: raise ["Didn't have permission to commit CVSROOT/loginfo.", 186: "Try to manually add the following line:", 187: trigger_command, 188: "Finally make commit the file to the repository"] 189: end 190: end 191: end
# File lib/rscm/scm/cvs.rb, line 116 116: def ls(relative_path) 117: prefix = relative_path == "" ? relative_path : "#{relative_path}/" 118: with_working_dir(@checkout_dir) do 119: cmd = "cvs -Q ls -l #{relative_path}" 120: Better.popen(cmd) do |io| 121: parse_ls_log(io, prefix) 122: end 123: end 124: end
# File lib/rscm/scm/cvs.rb, line 33 33: def move(relative_src, relative_dest) 34: FileUtils.mv(@checkout_dir + '/' + relative_src, @checkout_dir + '/' + relative_dest, :force=>true) 35: cvs(@checkout_dir, "rm #{relative_src}") 36: # This will fail if the directories are new. More advanced support for adding can be added if needed. 37: cvs(@checkout_dir, "add #{relative_dest}") 38: end
# File lib/rscm/scm/cvs.rb, line 107 107: def open(revision_file, &block) 108: with_working_dir(@checkout_dir) do 109: cmd = "cvs -Q update -p -r #{revision_file.native_revision_identifier} #{revision_file.path}" 110: Better.popen(cmd) do |io| 111: block.call io 112: end 113: end 114: end
# File lib/rscm/scm/cvs.rb, line 86 86: def revisions(from_identifier, to_identifier=Time.infinity, relative_path=nil) 87: checkout(to_identifier) unless uptodate?(to_identifier) # must checkout to get revisions 88: parse_log(changes_command(from_identifier, to_identifier, relative_path)) 89: end
# File lib/rscm/scm/cvs.rb, line 148 148: def trigger_installed?(trigger_command, trigger_files_checkout_dir) 149: loginfo_line = "#{mod} #{trigger_command}" 150: regex = Regexp.new(Regexp.escape(loginfo_line)) 151: 152: root_cvs = create_root_cvs(trigger_files_checkout_dir) 153: begin 154: root_cvs.checkout 155: loginfo = File.join(trigger_files_checkout_dir, "loginfo") 156: return false if !File.exist?(loginfo) 157: 158: # returns true if commented out. doesn't modify the file. 159: in_local_copy = LineEditor.comment_out(File.new(loginfo), regex, "# ", "") 160: # Also verify that loginfo has been committed back to the repo 161: entries = File.join(trigger_files_checkout_dir, "CVS", "Entries") 162: committed = File.mtime(entries) >= File.mtime(loginfo) 163: 164: in_local_copy && committed 165: rescue Exception => e 166: $stderr.puts(e.message) 167: $stderr.puts(e.backtrace.join("\n")) 168: false 169: end 170: end
# File lib/rscm/scm/cvs.rb, line 193 193: def uninstall_trigger(trigger_command, trigger_files_checkout_dir) 194: loginfo_line = "#{mod} #{trigger_command}" 195: regex = Regexp.new(Regexp.escape(loginfo_line)) 196: 197: root_cvs = create_root_cvs(trigger_files_checkout_dir) 198: root_cvs.checkout 199: loginfo_path = File.join(trigger_files_checkout_dir, "loginfo") 200: File.comment_out(loginfo_path, regex, "# ") 201: with_working_dir(trigger_files_checkout_dir) do 202: root_cvs.commit("Uninstalled trigger for CVS mod '#{mod}'") 203: end 204: raise "Couldn't uninstall/commit trigger to loginfo" if trigger_installed?(trigger_command, trigger_files_checkout_dir) 205: end