lib/origen/revision_control/git.rb in origen-0.1.3 vs lib/origen/revision_control/git.rb in origen-0.2.0
- old
+ new
@@ -23,13 +23,18 @@
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 options[:force]
- git 'reset HEAD'
- git 'pull', options
- git "checkout #{version} #{paths.join(' ')}", options
+ version = "origin/#{version}" if remote_branch?(version)
+ if paths == [local.to_s]
+ git "reset --hard #{version}"
+ else
+ git 'reset HEAD'
+ git 'pull', options
+ git "checkout #{version} #{paths.join(' ')}", options
+ 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'
@@ -61,12 +66,12 @@
def checkin(path = nil, options = {})
paths, options = clean_path(path, options)
# Can't check in unless we have the latest
if options[:force] && !options[:initial]
# Locally check in the given files
- checkin(paths.join(' '), local: true, verbose: false, comment: options[:comment])
- local_rev = current_commit
+ checkin(paths.join(' '), no_push: true, verbose: false, comment: options[: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
@@ -101,11 +106,11 @@
if options[:time]
cmd += " --date=\"#{options[:time].strftime('%a %b %e %H:%M:%S %Y %z')}\""
end
git cmd, options
end
- git "push origin #{current_branch}" unless options[:local]
+ git "push origin #{current_branch}" unless options[:no_push]
paths
end
# Returns true if the current user can checkin to the given repo (means has permission
# to push in Git terms)
@@ -159,12 +164,16 @@
}.merge(options)
cmd = "ls-files #{paths.first} --exclude-standard --others"
git(cmd, options).map(&:strip)
end
- def diff_cmd(file, version)
- "git difftool --tool tkdiff -y #{prefix_tag(version)} #{file}"
+ 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
def tag(id, options = {})
id = VersionString.new(id)
id = id.prefixed if id.semantic?
@@ -182,36 +191,96 @@
def current_branch
git('rev-parse --abbrev-ref HEAD', verbose: false).first
end
+ def current_commit(options = {})
+ options = {
+ short: true
+ }.merge(options)
+ commit = git('rev-parse HEAD', verbose: false).first
+ if options[:short]
+ commit[0, 11]
+ else
+ commit
+ end
+ end
+
# Returns true if the given tag already exists
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
+ # 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
+ 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
+ !git("ls-remote --heads #{rem} #{str}", verbose: false).empty?
+ end
+
def initialized?
File.exist?("#{local}/.git") &&
- git('remote -v', verbose: false).any? { |r| r =~ /#{remote_without_protocol}/ } &&
+ 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
# Delete everything in the given directory, or the whole repo
def delete_all(dir = nil, options = {})
paths, options = clean_path(dir, options)
files = git("ls-files #{paths.first}")
FileUtils.rm_f files
end
+ # 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
+ def self.user_name
+ git('config user.name', verbose: false).first
+ rescue
+ nil
+ end
+
+ # 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
+ def self.user_email
+ git('config user.email', verbose: false).first
+ rescue
+ nil
+ end
+
+ def user_name
+ self.class.user_name
+ end
+
+ def user_email
+ self.class.user_email
+ end
+
+ # Returns true if the remote points to a github url
+ def github?
+ !!(remote.to_s =~ /github.com/)
+ end
+
private
def remote_without_protocol
Pathname.new(remote.sub(/^.*:\/\//, ''))
end
+ def remote_without_protocol_and_user
+ Pathname.new(remote_without_protocol.to_s.sub(/^.*@/, ''))
+ end
+
def create_gitignore
c = Origen::Generator::Compiler.new
c.compile "#{Origen.top}/templates/git/gitignore.erb",
output_directory: local,
quiet: true,
@@ -221,35 +290,36 @@
def changes_pending_commit?
!(git('status --verbose', verbose: false).last =~ /^(no changes|nothing to commit)/)
end
- def current_commit
- git('rev-parse HEAD', verbose: false).first
- end
-
def initialize_local_dir
super
unless initialized?
Origen.log.debug "Initializing Git workspace at #{local}"
git 'init'
git "remote add origin #{remote}"
end
end
- # Execute a git operation, the resultant output is returned in an array
def git(command, options = {})
+ options[:local] = local
+ self.class.git(command, options)
+ end
+
+ # Execute a git operation, the resultant output is returned in an array
+ def self.git(command, options = {})
options = {
check_errors: true,
verbose: true
}.merge(options)
output = []
if options[:verbose]
Origen.log.info "git #{command}"
Origen.log.info ''
end
- Dir.chdir local do
+ chdir options[:local] do
Open3.popen2e("git #{command}") do |_stdin, stdout_err, wait_thr|
while line = stdout_err.gets
Origen.log.info line.strip if options[:verbose]
unless line.strip.empty?
output << line.strip
@@ -263,9 +333,19 @@
end
end
end
end
output
+ end
+
+ def self.chdir(dir)
+ if dir
+ Dir.chdir dir do
+ yield
+ end
+ else
+ yield
+ end
end
end
end
end