Class: Origen::RevisionControl::Git
- Defined in:
- lib/origen/revision_control/git.rb
Instance Attribute Summary
Attributes inherited from Base
Class Method Summary collapse
-
.origin ⇒ Object
Returns the origin for the PWD.
-
.user_email ⇒ Object
A class method is provided to fetch the user email since it is useful to have access to this when outside of an application workspace, e.g.
-
.user_name ⇒ Object
A class method is provided to fetch the user name since it is useful to have access to this when outside of an application workspace, e.g.
Instance Method Summary collapse
- #build(options = {}) ⇒ Object
-
#can_checkin? ⇒ Boolean
Returns true if the current user can checkin to the given repo (means has permission to push in Git terms).
- #changes(dir = nil, options = {}) ⇒ Object
- #checkin(path = nil, options = {}) ⇒ Object
- #checkout(path = nil, options = {}) ⇒ Object
- #current_branch ⇒ Object
- #current_commit(options = {}) ⇒ Object
-
#delete_all(dir = nil, options = {}) ⇒ Object
Delete everything in the given directory, or the whole repo.
- #diff_cmd(file, version = nil) ⇒ Object
-
#github? ⇒ Boolean
Returns true if the remote points to a github url.
- #initialized?(options = {}) ⇒ Boolean
- #local_modifications(dir = nil, options = {}) ⇒ Object
-
#remote_branch?(str) ⇒ Boolean
Returns true if the given string matches a branch name in the remote repo Origen.app.rc.remote_branch?(“master”) # => true Origen.app.rc.remote_branch?(“feature/exists”) # => true Origen.app.rc.remote_branch?(“feature/does_not_exist”) # => false.
- #root ⇒ Object
- #tag(id, options = {}) ⇒ Object
-
#tag_exists?(tag) ⇒ Boolean
Returns true if the given tag already exists.
- #unmanaged(dir = nil, options = {}) ⇒ Object
- #user_email ⇒ Object
- #user_name ⇒ Object
Methods inherited from Base
#dssc?, #git?, #initialize, #svn?
Constructor Details
This class inherits a constructor from Origen::RevisionControl::Base
Class Method Details
.origin ⇒ Object
Returns the origin for the PWD
5 6 7 8 9 10 11 12 |
# File 'lib/origen/revision_control/git.rb', line 5 def self.origin git('remote --verbose', verbose: false).each do |remote| if remote =~ /^origin\s+([^\s]+)/ return Regexp.last_match(1) end end nil end |
.user_email ⇒ Object
A class method is provided to fetch the user email since it is useful to have access to this when outside of an application workspace, e.g. when creating a new app
285 286 287 288 289 |
# File 'lib/origen/revision_control/git.rb', line 285 def self.user_email git('config user.email', verbose: false).first rescue nil end |
.user_name ⇒ Object
A class method is provided to fetch the user name since it is useful to have access to this when outside of an application workspace, e.g. when creating a new app
277 278 279 280 281 |
# File 'lib/origen/revision_control/git.rb', line 277 def self.user_name git('config user.name', verbose: false).first rescue nil end |
Instance Method Details
#build(options = {}) ⇒ Object
14 15 16 17 18 19 20 21 22 |
# File 'lib/origen/revision_control/git.rb', line 14 def build( = {}) if Dir["#{local}/*"].empty? || [:force] FileUtils.rm_rf(local.to_s) # Not using the regular 'git' method here since the local dir doesn't exist to CD into system "git clone #{remote} #{local}" else fail "The requested workspace is not empty: #{local}" end end |
#can_checkin? ⇒ Boolean
Returns true if the current user can checkin to the given repo (means has permission to push in Git terms)
131 132 133 134 135 136 |
# File 'lib/origen/revision_control/git.rb', line 131 def can_checkin? git('push --dry-run', verbose: false) true rescue false end |
#changes(dir = nil, options = {}) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/origen/revision_control/git.rb', line 138 def changes(dir = nil, = {}) paths, = clean_path(dir, ) = { verbose: false }.merge() # Pulls latest metadata from server, does not change workspace git 'fetch', version = [:version] || 'HEAD' objects = {} objects[:added] = git("diff --name-only --diff-filter=A #{version} #{paths.first}", ).map(&:strip) objects[:removed] = git("diff --name-only --diff-filter=D #{version} #{paths.first}", ).map(&:strip) objects[:changed] = git("diff --name-only --diff-filter=M #{version} #{paths.first}", ).map(&:strip) objects[:present] = !objects[:added].empty? || !objects[:removed].empty? || !objects[:changed].empty? # Return full paths objects[:added].map! { |i| "#{paths.first}/" + i } objects[:removed].map! { |i| "#{paths.first}/" + i } objects[:changed].map! { |i| "#{paths.first}/" + i } objects end |
#checkin(path = nil, options = {}) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/origen/revision_control/git.rb', line 76 def checkin(path = nil, = {}) paths, = clean_path(path, ) # Can't check in unless we have the latest if [:force] && ![:initial] # Locally check in the given files checkin(paths.join(' '), no_push: true, verbose: false, comment: [:comment]) local_rev = current_commit(short: false) # Pull latest checkout # Restore the given files to our previous version # Errors are ignored here since this can fail if the given file didn't exist until now, # in that case we already implicitly have the previous version git("checkout #{local_rev} -- #{paths.join(' ')}", check_errors: false) # Then proceed with checking them in as latest else checkout unless [:initial] end cmd = 'add' if [:unmanaged] cmd += ' -A' else cmd += ' -u' unless [:unmanaged] end cmd += " #{paths.join(' ')}" git cmd, if changes_pending_commit? cmd = 'commit' if [:comment] && ![:comment].strip.empty? cmd += " -m \"#{[:comment].strip}\"" else cmd += " -m \"No comment!\"" end if [:author] if [:author].respond_to?(:name_and_email) = [:author].name_and_email else = "#{[:author]} <>" end cmd += " --author=\"#{}\"" end if [:time] cmd += " --date=\"#{[:time].strftime('%a %b %e %H:%M:%S %Y %z')}\"" end git cmd, end unless [:no_push] cmd = "push origin #{current_branch}" cmd += ' -u' if [:initial] git cmd end paths end |
#checkout(path = nil, options = {}) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/origen/revision_control/git.rb', line 24 def checkout(path = nil, = {}) paths, = clean_path(path, ) # Pulls latest metadata from server, does not change workspace git 'fetch', version = [:version] || current_branch if version == 'HEAD' puts "Sorry, but you are not currently on a branch and I don't know which branch you want to checkout" puts 'Please supply a branch name as the version to checkout the latest version of it, e.g. origen rc co -v develop' exit 1 end if [:force] version = "origin/#{version}" if remote_branch?(version) if paths == [local.to_s] git "reset --hard #{version}", else git 'reset HEAD' git 'pull', git "checkout #{version} #{paths.join(' ')}", end else if paths.size > 1 || paths.first != local.to_s fail 'The Git driver does not support partial merge checkout, it has to be the whole workspace' end git 'reset HEAD' res = git 'stash', stashed = !res.any? { |l| l =~ /^No local changes to save/ } git 'pull', git "checkout #{version}", if stashed result = git 'stash pop', { check_errors: false }.merge() conflicts = [] result.each do |line| if line =~ /CONFLICT.* (.*)$/ conflicts << Regexp.last_match(1) end end git 'reset HEAD' unless conflicts.empty? Origen.log.info '' Origen.log.error 'Your local changes could not automatically merged into the following files, open them to fix the conflicts:' conflicts.each do |conflict| Origen.log.error " #{conflict}" end end end end paths end |
#current_branch ⇒ Object
206 207 208 |
# File 'lib/origen/revision_control/git.rb', line 206 def current_branch git('rev-parse --abbrev-ref HEAD', verbose: false).first end |
#current_commit(options = {}) ⇒ Object
210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/origen/revision_control/git.rb', line 210 def current_commit( = {}) = { short: true }.merge() commit = git('rev-parse HEAD', verbose: false).first if [:short] commit[0, 11] else commit end end |
#delete_all(dir = nil, options = {}) ⇒ Object
Delete everything in the given directory, or the whole repo
269 270 271 272 273 |
# File 'lib/origen/revision_control/git.rb', line 269 def delete_all(dir = nil, = {}) paths, = clean_path(dir, ) files = git("ls-files #{paths.first}") FileUtils.rm_f files end |
#diff_cmd(file, version = nil) ⇒ Object
183 184 185 186 187 188 189 |
# File 'lib/origen/revision_control/git.rb', line 183 def diff_cmd(file, version = nil) if version "git difftool --tool tkdiff -y #{prefix_tag(version)} #{file}" else "git difftool --tool tkdiff -y #{file}" end end |
#github? ⇒ Boolean
Returns true if the remote points to a github url
300 301 302 |
# File 'lib/origen/revision_control/git.rb', line 300 def github? !!(remote.to_s =~ /github.com/) end |
#initialized?(options = {}) ⇒ Boolean
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/origen/revision_control/git.rb', line 247 def initialized?( = {}) @hierarchy_searched ||= begin path = @local.dup until path.root? || File.exist?("#{local}/.git") if File.exist?("#{path}/.git") if [:allow_local_adjustment] @local = path else fail "Requested local repository #{local} is within existing local repository #{path}" end else path = path.parent end end true end File.exist?("#{local}/.git") && git('remote -v', verbose: false).any? { |r| r =~ /#{remote_without_protocol_and_user}/ || r =~ /#{remote_without_protocol_and_user.to_s.gsub(':', "\/")}/ } && !git('status', verbose: false).any? { |l| l =~ /^#? ?Initial commit$/ } end |
#local_modifications(dir = nil, options = {}) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/origen/revision_control/git.rb', line 161 def local_modifications(dir = nil, = {}) paths, = clean_path(dir, ) = { verbose: false }.merge() cmd = 'diff --name-only' dir = " #{paths.first}" unstaged = git(cmd + dir, ).map(&:strip) staged = git(cmd + ' --cached' + dir, ).map(&:strip) unstaged + staged end |
#remote_branch?(str) ⇒ Boolean
233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/origen/revision_control/git.rb', line 233 def remote_branch?(str) # Github doesn't like the ssh:// for this command, whereas Stash seems # to require it. if github? rem = remote_without_protocol else rem = remote end # check if matches 40 digit hex string followed by branch name git("ls-remote --heads #{remote} #{str}", verbose: false).any? do |line| line =~ /^[0-9a-f]{40}\s+[a-zA-Z]/ end end |
#root ⇒ Object
202 203 204 |
# File 'lib/origen/revision_control/git.rb', line 202 def root Pathname.new(git('rev-parse --show-toplevel', verbose: false).first.strip) end |
#tag(id, options = {}) ⇒ Object
191 192 193 194 195 196 197 198 199 200 |
# File 'lib/origen/revision_control/git.rb', line 191 def tag(id, = {}) id = VersionString.new(id) id = id.prefixed if id.semantic? if [:comment] git "tag -a #{id} -m \"#{[:comment]}\"" else git "tag #{id}" end git "push origin #{id}" end |
#tag_exists?(tag) ⇒ Boolean
Returns true if the given tag already exists
223 224 225 226 227 |
# File 'lib/origen/revision_control/git.rb', line 223 def tag_exists?(tag) git('fetch', verbose: false) unless @all_tags_fetched @all_tags_fetched = true git('tag', verbose: false).include?(tag.to_s) end |
#unmanaged(dir = nil, options = {}) ⇒ Object
174 175 176 177 178 179 180 181 |
# File 'lib/origen/revision_control/git.rb', line 174 def unmanaged(dir = nil, = {}) paths, = clean_path(dir, ) = { verbose: false }.merge() cmd = "ls-files #{paths.first} --exclude-standard --others" git(cmd, ).map(&:strip) end |
#user_email ⇒ Object
295 296 297 |
# File 'lib/origen/revision_control/git.rb', line 295 def user_email self.class.user_email end |
#user_name ⇒ Object
291 292 293 |
# File 'lib/origen/revision_control/git.rb', line 291 def user_name self.class.user_name end |