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
- .to_utf8(str) ⇒ Object
- .toplevel_dir ⇒ Object
Class Method Details
.branch_commits(treeish) ⇒ Object
104 105 106 107 108 109 110 |
# File 'lib/git_commit_notifier/git.rb', line 104 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
133 134 135 |
# File 'lib/git_commit_notifier/git.rb', line 133 def branch_head(treeish) from_shell("git rev-parse #{treeish}").strip end |
.branch_heads ⇒ Object
112 113 114 115 |
# File 'lib/git_commit_notifier/git.rb', line 112 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
72 73 74 75 76 |
# File 'lib/git_commit_notifier/git.rb', line 72 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'
52 53 54 |
# File 'lib/git_commit_notifier/git.rb', line 52 def describe(rev) from_shell("git describe --always #{rev.strip}").strip end |
.from_shell(cmd) ⇒ String
Runs specified command and gets its output.
15 16 17 18 19 |
# File 'lib/git_commit_notifier/git.rb', line 15 def from_shell(cmd) r = `#{cmd}` raise ArgumentError.new("#{cmd} failed") unless $?.exitstatus.zero? to_utf8(r) end |
.git_dir ⇒ Object
117 118 119 |
# File 'lib/git_commit_notifier/git.rb', line 117 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.
25 26 27 28 29 30 |
# File 'lib/git_commit_notifier/git.rb', line 25 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.
148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/git_commit_notifier/git.rb', line 148 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
62 63 64 |
# File 'lib/git_commit_notifier/git.rb', line 62 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.
268 269 270 271 272 |
# File 'lib/git_commit_notifier/git.rb', line 268 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
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 187 188 189 190 191 |
# File 'lib/git_commit_notifier/git.rb', line 162 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.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/git_commit_notifier/git.rb', line 217 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.
234 235 236 237 238 239 240 241 |
# File 'lib/git_commit_notifier/git.rb', line 234 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.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/git_commit_notifier/git.rb', line 248 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
125 126 127 |
# File 'lib/git_commit_notifier/git.rb', line 125 def rev_parse(param) from_shell("git rev-parse '#{param}'").strip end |
.rev_type(rev) ⇒ Object
193 194 195 196 197 |
# File 'lib/git_commit_notifier/git.rb', line 193 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.
85 86 87 88 |
# File 'lib/git_commit_notifier/git.rb', line 85 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
129 130 131 |
# File 'lib/git_commit_notifier/git.rb', line 129 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
39 40 41 42 43 44 45 46 |
# File 'lib/git_commit_notifier/git.rb', line 39 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
95 96 97 98 99 100 101 102 |
# File 'lib/git_commit_notifier/git.rb', line 95 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
199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/git_commit_notifier/git.rb', line 199 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 |
.to_utf8(str) ⇒ Object
6 7 8 9 10 |
# File 'lib/git_commit_notifier/git.rb', line 6 def to_utf8(str) return str unless str.respond_to?(:force_encoding) str.force_encoding(Encoding::UTF_8) str end |
.toplevel_dir ⇒ Object
121 122 123 |
# File 'lib/git_commit_notifier/git.rb', line 121 def toplevel_dir from_shell("git rev-parse --show-toplevel").strip end |