Class: GitCommitNotifier::Git
- Inherits:
-
Object
- Object
- GitCommitNotifier::Git
- Defined in:
- lib/git_commit_notifier/git.rb
Overview
Git methods
Class Method Summary collapse
- .branch_commits(treeish) ⇒ Object
- .branch_head(treeish) ⇒ Object
- .branch_heads ⇒ Object
-
.changed_files(rev1, rev2) ⇒ Array(String)
Runs
git logand extract filenames only. -
.describe(rev) ⇒ String
Runs `git describe'.
-
.from_shell(cmd) ⇒ String
Runs specified command and gets its output.
- .git_dir ⇒ Object
-
.lines_from_shell(cmd) ⇒ Enumerable(String)
Runs specified command and gets its output as array of lines.
-
.list_of_commits_between_current_commit_and_last_tag(tag_name, rev) ⇒ Array
Lists commits between specified rev and closest annotated tag.
-
.log(rev1, rev2) ⇒ String
Runs
git log. -
.mailing_list_address ⇒ String
Gets mailing list address.
- .new_commits(oldrev, newrev, refname, unique_to_current_branch) ⇒ Object
-
.repo_name ⇒ String
Gets repository name.
-
.repo_name_real ⇒ String
Gets repository name.
-
.repo_name_with_parent ⇒ String
Human readable repository name.
- .rev_parse(param) ⇒ Object
- .rev_type(rev) ⇒ Object
-
.sha_of_filename(rev, filename) ⇒ String
Returns sha1 of the file after the most recent commit.
- .short_commit_id(param) ⇒ Object
-
.show(rev, opts = {}) ⇒ String
Runs
git show. -
.split_status(rev1, rev2) ⇒ Hash(Array)
splits the output of changed_files.
- .tag_info(refname) ⇒ Object
- .toplevel_dir ⇒ Object
Class Method Details
.branch_commits(treeish) ⇒ Object
99 100 101 102 103 104 105 |
# File 'lib/git_commit_notifier/git.rb', line 99 def branch_commits(treeish) args = branch_heads - [ branch_head(treeish) ] args.map! { |tree| "^#{tree}" } args << treeish lines = lines_from_shell("git rev-list #{args.join(' ')}") lines.to_a.map { |commit| commit.chomp } end |
.branch_head(treeish) ⇒ Object
128 129 130 |
# File 'lib/git_commit_notifier/git.rb', line 128 def branch_head(treeish) from_shell("git rev-parse #{treeish}").strip end |
.branch_heads ⇒ Object
107 108 109 110 |
# File 'lib/git_commit_notifier/git.rb', line 107 def branch_heads lines = lines_from_shell("git rev-parse --branches") lines.to_a.map { |head| head.chomp } end |
.changed_files(rev1, rev2) ⇒ Array(String)
uses "--pretty=oneline" and "--name-status" and "-M" options.
Runs git log and extract filenames only
67 68 69 70 71 |
# File 'lib/git_commit_notifier/git.rb', line 67 def changed_files(rev1, rev2) lines = lines_from_shell("git log #{rev1}..#{rev2} --name-status --pretty=oneline -M#{GitCommitNotifier::CommitHook.config['similarity_detection_threshold'] || "0.5"}") lines = lines.select {|line| line =~ /^\w{1}\s+\w+/} # grep out only filenames lines.uniq end |
.describe(rev) ⇒ String
Runs `git describe'
47 48 49 |
# File 'lib/git_commit_notifier/git.rb', line 47 def describe(rev) from_shell("git describe --always #{rev.strip}").strip end |
.from_shell(cmd) ⇒ String
Runs specified command and gets its output.
9 10 11 12 13 14 |
# File 'lib/git_commit_notifier/git.rb', line 9 def from_shell(cmd) r = `#{cmd}` raise ArgumentError.new("#{cmd} failed") unless $?.exitstatus.zero? r.force_encoding(Encoding::UTF_8) if r.respond_to?(:force_encoding) r end |
.git_dir ⇒ Object
112 113 114 |
# File 'lib/git_commit_notifier/git.rb', line 112 def git_dir from_shell("git rev-parse --git-dir").strip end |
.lines_from_shell(cmd) ⇒ Enumerable(String)
Runs specified command and gets its output as array of lines.
20 21 22 23 24 25 |
# File 'lib/git_commit_notifier/git.rb', line 20 def lines_from_shell(cmd) lines = from_shell(cmd) # Ruby 1.9 tweak. lines = lines.lines if lines.respond_to?(:lines) lines end |
.list_of_commits_between_current_commit_and_last_tag(tag_name, rev) ⇒ Array
There have been many complaints about using git describe to obtain this information but, this looked like the best way to obtain the information here. Here is a link http://www.xerxesb.com/2010/git-describe-and-the-tale-of-the-wrong-commits/ discussing, the way git-describe handles the problem of finding the nearest commit with a tag. Looking forward to someone coming up with a better way.
Lists commits between specified rev and closest annotated tag.
Uses git describe to obtain information.
143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/git_commit_notifier/git.rb', line 143 def list_of_commits_between_current_commit_and_last_tag(tag_name, rev) result = Array.new lines = from_shell("git describe --abbrev=0 #{rev}^1 2> /dev/null | cat ").strip # the `cat` is used to suppress the error that might arise when handling the case of the first commit if lines.length != 1 previous_tag = lines list_of_commits = lines_from_shell("git log #{previous_tag}..#{tag_name} --format='%H::::::%s'") list_of_commits.each do |row| result << Array.new(row.split("::::::")) end end result end |
.log(rev1, rev2) ⇒ String
uses "--pretty=fuller" option.
Runs git log
57 58 59 |
# File 'lib/git_commit_notifier/git.rb', line 57 def log(rev1, rev2) from_shell("git log --pretty=fuller #{rev1}..#{rev2}").strip end |
.mailing_list_address ⇒ String
mailing list address retrieved through git config hooks.mailinglist call.
Gets mailing list address.
263 264 265 266 267 |
# File 'lib/git_commit_notifier/git.rb', line 263 def mailing_list_address from_shell("git config hooks.mailinglist").strip rescue ArgumentError nil end |
.new_commits(oldrev, newrev, refname, unique_to_current_branch) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/git_commit_notifier/git.rb', line 157 def new_commits(oldrev, newrev, refname, unique_to_current_branch) # We want to get the set of commits (^B1 ^B2 ... ^oldrev newrev) # Where B1, B2, ..., are any other branch a = Array.new # If we want to include only those commits that are # unique to this branch, then exclude commits that occur on # other branches if unique_to_current_branch # Make a set of all branches, not'd (^BCURRENT ^B1 ^B2...) not_branches = lines_from_shell("git rev-parse --not --branches") a = not_branches.map { |l| l.chomp } # Remove the current branch (^BCURRENT) from the set current_branch = rev_parse(refname) a.delete_at a.index("^#{current_branch}") unless a.index("^#{current_branch}").nil? end # Add not'd oldrev (^oldrev) a.push("^#{oldrev}") unless oldrev =~ /^0+$/ # Add newrev a.push(newrev) # We should now have ^B1... ^oldrev newrev # Get all the commits that match that specification lines = lines_from_shell("git rev-list --reverse #{a.join(' ')}") lines.to_a.map { |l| l.chomp } end |
.repo_name ⇒ String
Tries to gets human readable repository name through git config hooks.emailprefix call.
If it's not specified then returns directory name (except '.git' suffix if exists).
Gets repository name.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/git_commit_notifier/git.rb', line 212 def repo_name git_prefix = begin from_shell("git config hooks.emailprefix").strip rescue ArgumentError '' end return git_prefix unless git_prefix.empty? git_path = toplevel_dir # In a bare repository, toplevel directory is empty. Revert to git_dir instead. if git_path.empty? git_path = git_dir end File.(git_path).split("/").last.sub(/\.git$/, '') end |
.repo_name_real ⇒ String
Gets repository name.
229 230 231 232 233 234 235 236 |
# File 'lib/git_commit_notifier/git.rb', line 229 def repo_name_real git_path = toplevel_dir # In a bare repository, toplevel directory is empty. Revert to git_dir instead. if git_path.empty? git_path = git_dir end File.(git_path).split("/").last end |
.repo_name_with_parent ⇒ String
Returns Human readable repository name.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/git_commit_notifier/git.rb', line 243 def repo_name_with_parent git_prefix = begin from_shell("git config hooks.emailprefix").strip rescue ArgumentError '' end return git_prefix unless git_prefix.empty? git_path = toplevel_dir # In a bare repository, toplevel directory is empty. Revert to git_dir instead. if git_path.empty? git_path = git_dir end name_with_parent = File.(git_path).scan(/[a-zA-z0-9\-_]+\/[a-zA-Z0-9\-_]+.git$/).first; return name_with_parent.sub(/\.git$/, '') unless name_with_parent.empty? File.(git_path).split("/").last.sub(/\.git$/, '') end |
.rev_parse(param) ⇒ Object
120 121 122 |
# File 'lib/git_commit_notifier/git.rb', line 120 def rev_parse(param) from_shell("git rev-parse '#{param}'").strip end |
.rev_type(rev) ⇒ Object
188 189 190 191 192 |
# File 'lib/git_commit_notifier/git.rb', line 188 def rev_type(rev) from_shell("git cat-file -t '#{rev}' 2> /dev/null").strip rescue ArgumentError nil end |
.sha_of_filename(rev, filename) ⇒ String
It was required as when there is a file which is renamed, and it has a 100% similarity index, its sha is not included in the git-show output.
Returns sha1 of the file after the most recent commit.
Runs git show #{rev}:#{filename} | git hash-object --stdin to return the sha of the file.
80 81 82 83 |
# File 'lib/git_commit_notifier/git.rb', line 80 def sha_of_filename(rev, filename) lines = from_shell("git show #{rev}:#{filename} | git hash-object --stdin") lines.strip end |
.short_commit_id(param) ⇒ Object
124 125 126 |
# File 'lib/git_commit_notifier/git.rb', line 124 def short_commit_id(param) from_shell("git rev-parse --short '#{param}'").strip end |
.show(rev, opts = {}) ⇒ String
uses "--pretty=fuller" and "-M" option.
Runs git show
34 35 36 37 38 39 40 41 |
# File 'lib/git_commit_notifier/git.rb', line 34 def show(rev, opts = {}) gitopt = " --date=rfc2822" gitopt += " --pretty=fuller" gitopt += " -M#{GitCommitNotifier::CommitHook.config['similarity_detection_threshold'] || "0.5"}" gitopt += " -w" if opts[:ignore_whitespace] == 'all' gitopt += " -b" if opts[:ignore_whitespace] == 'change' from_shell("git show #{rev.strip}#{gitopt}") end |
.split_status(rev1, rev2) ⇒ Hash(Array)
splits the output of changed_files
90 91 92 93 94 95 96 97 |
# File 'lib/git_commit_notifier/git.rb', line 90 def split_status(rev1, rev2) lines = changed_files(rev1, rev2) modified = lines.map { |l| l.gsub(/M\s/,'').strip if l[0,1] == 'M' }.select { |l| !l.nil? } added = lines.map { |l| l.gsub(/A\s/,'').strip if l[0,1] == 'A' }.select { |l| !l.nil? } deleted = lines.map { |l| l.gsub(/D\s/,'').strip if l[0,1] == 'D' }.select { |l| !l.nil? } renamed = lines.map { |l| l.gsub(/R\d+\s/,'').strip if l[0,1] == 'R' }.select { |l| !l.nil? } { :m => modified, :a => added, :d => deleted , :r => renamed} end |
.tag_info(refname) ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/git_commit_notifier/git.rb', line 194 def tag_info(refname) fields = [ ':tagobject => %(*objectname)', ':tagtype => %(*objecttype)', ':taggername => %(taggername)', ':taggeremail => %(taggeremail)', ':subject => %(subject)', ':contents => %(contents)' ] joined_fields = fields.join(",") hash_script = from_shell("git for-each-ref --shell --format='{ #{joined_fields} }' #{refname}") eval(hash_script) end |
.toplevel_dir ⇒ Object
116 117 118 |
# File 'lib/git_commit_notifier/git.rb', line 116 def toplevel_dir from_shell("git rev-parse --show-toplevel").strip end |