Class: ScmWorkspace
- Inherits:
-
Object
- Object
- ScmWorkspace
- Defined in:
- lib/scm_workspace.rb,
lib/scm_workspace/version.rb
Defined Under Namespace
Classes: Error
Constant Summary collapse
- CONFIGURE_OPTIONS =
{ svn: { "A" => "authors_file", "b" => "branches", "m!" => "minimize_rul", "q+" => "quiet", "r" => "revision", "s" => "stdlayout", "t" => "tags", "T" => "trunk", }, git: { 'n' => 'no_checkout', 'l' => 'local', 's' => 'shared', 'o' => 'origin', 'b' => 'branch', 'u' => 'upload_pack', 'c' => 'config', } }
- VERSION =
"0.3.4"
Instance Attribute Summary collapse
- #logger ⇒ Object
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#svn_branch_prefix ⇒ Object
Returns the value of attribute svn_branch_prefix.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
Class Method Summary collapse
Instance Method Summary collapse
-
#accessible? ⇒ Boolean
submoduleでない場合 true submoduleの場合 true gitの対象外の場合 false.
- #branch_names ⇒ Object
- #checkout(branch_name) ⇒ Object
- #clear ⇒ Object
- #cleared? ⇒ Boolean
- #commit_info ⇒ Object
- #configure(url) ⇒ Object
-
#configured? ⇒ Boolean
submoduleでない場合 true submoduleの場合 false gitの対象外の場合 false.
- #contains?(obj) ⇒ Boolean
- #current_branch_name ⇒ Object
- #current_commit_key ⇒ Object
- #current_sha ⇒ Object
- #current_tag_names ⇒ Object
- #empty? ⇒ Boolean
- #fetch ⇒ Object
- #fileutils ⇒ Object
- #git_current_branch_name(dir = repo_dir) ⇒ Object
- #git_repo? ⇒ Boolean
- #in_root ⇒ Object (also: #in_repo_dir)
-
#initialize(config, options = {}) ⇒ ScmWorkspace
constructor
A new instance of ScmWorkspace.
- #remotes ⇒ Object
- #repo_dir ⇒ Object
- #reset_hard(tag) ⇒ Object (also: #move)
- #scm_type ⇒ Object
- #status ⇒ Object
- #svn_current_branch_name ⇒ Object
- #svn_info ⇒ Object
- #svn_repo? ⇒ Boolean
- #system!(cmd) ⇒ Object
- #system_at_root!(cmd) ⇒ Object
- #tag_names ⇒ Object
- #url ⇒ Object
Constructor Details
#initialize(config, options = {}) ⇒ ScmWorkspace
Returns a new instance of ScmWorkspace.
21 22 23 24 25 26 |
# File 'lib/scm_workspace.rb', line 21 def initialize(config, = {}) @root = config[:workspace] @logger = [:logger] @verbose = [:verbose] || (ENV["VERBOSE"] =~ /true|yes|on/) @svn_branch_prefix = [:svn_branch_prefix] || ENV["SVN_BRANCH_PREFIX"] || "branches" end |
Instance Attribute Details
#logger ⇒ Object
28 29 30 |
# File 'lib/scm_workspace.rb', line 28 def logger @logger ||= Tengine::Support::NullLogger.new end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
17 18 19 |
# File 'lib/scm_workspace.rb', line 17 def root @root end |
#svn_branch_prefix ⇒ Object
Returns the value of attribute svn_branch_prefix.
19 20 21 |
# File 'lib/scm_workspace.rb', line 19 def svn_branch_prefix @svn_branch_prefix end |
#verbose ⇒ Object
Returns the value of attribute verbose.
20 21 22 |
# File 'lib/scm_workspace.rb', line 20 def verbose @verbose end |
Class Method Details
.guess_scm_type(url) ⇒ Object
345 346 347 348 349 350 351 |
# File 'lib/scm_workspace.rb', line 345 def guess_scm_type(url) case url when /\Agit:\/\//, /\Agit\@/, /\.git\Z/ then :git when /svn/ then :svn else nil end end |
Instance Method Details
#accessible? ⇒ Boolean
submoduleでない場合 true submoduleの場合 true gitの対象外の場合 false
271 272 273 |
# File 'lib/scm_workspace.rb', line 271 def accessible? File.exist?(File.join(repo_dir, ".git")) end |
#branch_names ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/scm_workspace.rb', line 188 def branch_names return nil unless accessible? case scm_type when :git then result = system_at_root!("git branch -r").lines.map{|path| path.sub(/\A\s*origin\//, '').strip } result.delete_if{|name| name =~ /\AHEAD ->/} result when :svn then system_at_root!("git branch -r").lines.map{|path| path.strip } end end |
#checkout(branch_name) ⇒ Object
107 108 109 110 111 112 113 |
# File 'lib/scm_workspace.rb', line 107 def checkout(branch_name) logger.info("-" * 100) system_at_root!("git checkout #{branch_name}") case scm_type when :git then system_at_root!("git reset --hard origin/#{branch_name}") end end |
#clear ⇒ Object
89 90 91 92 93 94 95 96 97 98 |
# File 'lib/scm_workspace.rb', line 89 def clear return unless Dir.exist?(root) fileutils.chdir(root) do (Dir.glob("*") + Dir.glob(".*")).each do |d| next if d =~ /\A\.+\Z/ logger.info("remove_entry_secure #{d.inspect}") fileutils.remove_entry_secure(d) end end end |
#cleared? ⇒ Boolean
283 284 285 286 |
# File 'lib/scm_workspace.rb', line 283 def cleared? # !configured? empty? end |
#commit_info ⇒ Object
179 180 181 182 183 184 185 186 |
# File 'lib/scm_workspace.rb', line 179 def commit_info { "scm_type" => scm_type.to_s, "url" => url, "branch" => current_branch_name, "commit_key" => current_commit_key } end |
#configure(url) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/scm_workspace.rb', line 63 def configure(url) unless empty? msg = "#{repo_dir} is not empty. You must clear it" msg << "\nls -la #{repo_dir}" << `ls -la #{repo_dir}` if verbose raise msg end url, opt = url.split(/\s+/, 2) scm_type = self.class.guess_scm_type(url) case scm_type when :git then logger.info("*" * 100) logger.info("SCM configure") system!("git clone #{url} #{repo_dir} #{opt}") when :svn then fileutils.chdir(@root) do cmd = "git svn clone #{url} #{repo_dir} #{opt}" cmd << " > /dev/null 2>&1" unless verbose logger.info("*" * 100) logger.info("SCM configure") system(cmd) end else raise "Unknown SCM type: #{url}" end end |
#configured? ⇒ Boolean
submoduleでない場合 true submoduleの場合 false gitの対象外の場合 false
278 279 280 |
# File 'lib/scm_workspace.rb', line 278 def configured? Dir.exist?(File.join(repo_dir, ".git")) end |
#contains?(obj) ⇒ Boolean
288 289 290 |
# File 'lib/scm_workspace.rb', line 288 def contains?(obj) !!system_at_root!("git show #{obj} --oneline --quiet") rescue false end |
#current_branch_name ⇒ Object
220 221 222 223 224 225 226 |
# File 'lib/scm_workspace.rb', line 220 def current_branch_name return nil unless accessible? case scm_type when :git then git_current_branch_name when :svn then svn_current_branch_name end end |
#current_commit_key ⇒ Object
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/scm_workspace.rb', line 162 def current_commit_key return nil unless accessible? result = current_sha case scm_type when :svn then rev = nil cnt = 0 while rev.nil? rev = in_repo_dir{ `git svn find-rev #{result}`.strip } cnt += 1 raise "failed to get svn revision for #{result}" if cnt > 10 end result << ':' << rev end result end |
#current_sha ⇒ Object
157 158 159 160 |
# File 'lib/scm_workspace.rb', line 157 def current_sha return nil unless accessible? system_at_root!("git log -1").scan(/^commit ([0-9a-f]+)$/).flatten.first end |
#current_tag_names ⇒ Object
258 259 260 261 |
# File 'lib/scm_workspace.rb', line 258 def current_tag_names return nil unless accessible? system_at_root!("git describe --tags #{current_sha}").lines.map(&:strip) rescue [] end |
#empty? ⇒ Boolean
100 101 102 103 104 105 |
# File 'lib/scm_workspace.rb', line 100 def empty? return true unless Dir.exist?(root) FileUtils.chdir(root) do return (Dir.glob("*") + Dir.glob(".*")).reject{|d| d =~ /\A\.+\Z/}.empty? end end |
#fetch ⇒ Object
124 125 126 127 128 129 130 |
# File 'lib/scm_workspace.rb', line 124 def fetch logger.info("-" * 100) case scm_type when :git then system_at_root!("git fetch origin") when :svn then system_at_root!("git svn fetch") end end |
#fileutils ⇒ Object
32 33 34 |
# File 'lib/scm_workspace.rb', line 32 def fileutils @fileutils ||= FileUtils.with_logger(logger) end |
#git_current_branch_name(dir = repo_dir) ⇒ Object
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/scm_workspace.rb', line 228 def git_current_branch_name(dir = repo_dir) return nil unless Dir.exist?(dir) FileUtils.chdir(dir) do # http://qiita.com/sugyan/items/83e060e895fa8ef2038c result = `git symbolic-ref --short HEAD`.strip return result unless result.nil? || result.empty? result = `git status`.scan(/On branch\s*(.+)\s*$/).flatten.first return result unless result.nil? || result.empty? work = `git log --decorate -1`.scan(/^commit\s[0-9a-f]+\s\((.+)\)/). flatten.first.split(/,/).map(&:strip).reject{|s| s =~ /HEAD\Z/} r = work.select{|s| s =~ /origin\//}.first r ||= work.first result = r.nil? ? nil : r.sub(/\Aorigin\//, '') return result end rescue => e # puts "[#{e.class}] #{e.message}" # puts "Dir.pwd: #{Dir.pwd}" # puts "git status\n" << `git status` raise e end |
#git_repo? ⇒ Boolean
315 316 317 318 |
# File 'lib/scm_workspace.rb', line 315 def git_repo? return nil unless accessible? !remotes.empty? rescue false end |
#in_root ⇒ Object Also known as: in_repo_dir
337 338 339 340 341 |
# File 'lib/scm_workspace.rb', line 337 def in_root fileutils.chdir(repo_dir) do return yield end end |
#remotes ⇒ Object
200 201 202 203 204 205 |
# File 'lib/scm_workspace.rb', line 200 def remotes system_at_root!("git remote -v show").lines.each_with_object({}) do |line, d| name, url, other = line.strip.split(/[\t\s]+/, 3) d[name] = url end end |
#repo_dir ⇒ Object
264 265 266 |
# File 'lib/scm_workspace.rb', line 264 def repo_dir @root end |
#reset_hard(tag) ⇒ Object Also known as: move
115 116 117 118 119 120 121 |
# File 'lib/scm_workspace.rb', line 115 def reset_hard(tag) logger.info("-" * 100) case scm_type when :git then system_at_root!("git reset --hard #{tag}") when :svn then raise "Illegal operation for svn" end end |
#scm_type ⇒ Object
325 326 327 328 329 330 |
# File 'lib/scm_workspace.rb', line 325 def scm_type return nil unless accessible? return :git if git_repo? return :svn if svn_repo? nil end |
#status ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/scm_workspace.rb', line 132 def status logger.info("-" * 100) case scm_type when :git then status_text = system_at_root!("git status") # in_repo_dir{ `git status` } value = status_text.scan(/Your branch is behind 'origin\/#{current_branch_name}' by (\d+\s+commits)/) if value && !value.empty? "There is/are #{value.flatten.join}" else "everything is up-to-dated." end when :svn then status_text = system_at_root!("git log --branches --oneline #{current_sha}..") lines = status_text.split(/\n/) if lines.empty? "everything is up-to-dated." else latest_sha = lines.first "There is/are #{lines.length} commits." << " current revision: " << system_at_root!("git svn find-rev #{current_sha}").strip << " latest revision: " << system_at_root!("git svn find-rev #{latest_sha}").strip end end end |
#svn_current_branch_name ⇒ Object
250 251 252 253 254 255 256 |
# File 'lib/scm_workspace.rb', line 250 def svn_current_branch_name info = svn_info r = info[:url].sub(info[:repository_root], '') r.sub!(/\A\//, '') r.sub!(svn_branch_prefix + "/", '') r end |
#svn_info ⇒ Object
332 333 334 335 |
# File 'lib/scm_workspace.rb', line 332 def svn_info txt = system_at_root!("git svn info") return txt.scan(/^(.+?): (.*)$/).each_with_object({}){|(k,v), d| d[k.downcase.gsub(/\s/, '_').to_sym] = v } end |
#svn_repo? ⇒ Boolean
320 321 322 323 |
# File 'lib/scm_workspace.rb', line 320 def svn_repo? return nil unless accessible? Dir.exist?(File.join(repo_dir, '.git', 'svn')) end |
#system!(cmd) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/scm_workspace.rb', line 36 def system!(cmd) logger.info("executing: #{cmd}") buf = [] IO.popen("#{cmd} 2>&1") do |io| while line = io.gets # puts line buf << line end end if $?.exitstatus == 0 msg = "\e[33mSUCCESS: %s\e[0m" % cmd r = buf.join msg << "\n" << r.strip if verbose logger.info(msg) return r else msg = "\e[31mFAILURE: %s\n%s\e[0m" % [cmd, buf.join.strip] logger.error(msg) raise Error, msg end end |
#system_at_root!(cmd) ⇒ Object
59 60 61 |
# File 'lib/scm_workspace.rb', line 59 def system_at_root!(cmd) fileutils.chdir(root){ system!(cmd) } end |
#tag_names ⇒ Object
207 208 209 210 |
# File 'lib/scm_workspace.rb', line 207 def tag_names return nil unless accessible? system_at_root!("git tag").lines.map{|path| path.strip.strip } end |
#url ⇒ Object
212 213 214 215 216 217 218 |
# File 'lib/scm_workspace.rb', line 212 def url return nil unless accessible? case scm_type when :git then remotes["origin"] when :svn then svn_info[:repository_root] end end |