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
106 107 108 109 110 111 112 |
# File 'lib/git_commit_notifier/git.rb', line 106 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
135 136 137 |
# File 'lib/git_commit_notifier/git.rb', line 135 def branch_head(treeish) from_shell("git rev-parse #{treeish}").strip end |
.branch_heads ⇒ Object
114 115 116 117 |
# File 'lib/git_commit_notifier/git.rb', line 114 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
74 75 76 77 78 |
# File 'lib/git_commit_notifier/git.rb', line 74 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'
54 55 56 |
# File 'lib/git_commit_notifier/git.rb', line 54 def describe(rev) from_shell("git describe --always #{rev.strip}").strip end |
.from_shell(cmd) ⇒ String
Runs specified command and gets its output.
17 18 19 20 21 |
# File 'lib/git_commit_notifier/git.rb', line 17 def from_shell(cmd) r = `#{cmd}` raise ArgumentError.new("#{cmd} failed") unless $?.exitstatus.zero? to_utf8(r) end |
.git_dir ⇒ Object
119 120 121 |
# File 'lib/git_commit_notifier/git.rb', line 119 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.
27 28 29 30 31 32 |
# File 'lib/git_commit_notifier/git.rb', line 27 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.
150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/git_commit_notifier/git.rb', line 150 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
64 65 66 |
# File 'lib/git_commit_notifier/git.rb', line 64 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.
270 271 272 273 274 |
# File 'lib/git_commit_notifier/git.rb', line 270 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
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 192 193 |
# File 'lib/git_commit_notifier/git.rb', line 164 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.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/git_commit_notifier/git.rb', line 219 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.
236 237 238 239 240 241 242 243 |
# File 'lib/git_commit_notifier/git.rb', line 236 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.
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/git_commit_notifier/git.rb', line 250 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
127 128 129 |
# File 'lib/git_commit_notifier/git.rb', line 127 def rev_parse(param) from_shell("git rev-parse '#{param}'").strip end |
.rev_type(rev) ⇒ Object
195 196 197 198 199 |
# File 'lib/git_commit_notifier/git.rb', line 195 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.
87 88 89 90 |
# File 'lib/git_commit_notifier/git.rb', line 87 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
131 132 133 |
# File 'lib/git_commit_notifier/git.rb', line 131 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
41 42 43 44 45 46 47 48 |
# File 'lib/git_commit_notifier/git.rb', line 41 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
97 98 99 100 101 102 103 104 |
# File 'lib/git_commit_notifier/git.rb', line 97 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
201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/git_commit_notifier/git.rb', line 201 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 11 12 |
# File 'lib/git_commit_notifier/git.rb', line 6 def to_utf8(str) return str unless str.respond_to?(:force_encoding) str = str.force_encoding(Encoding::UTF_8) return str if str.valid_encoding? str = str.force_encoding(Encoding::BINARY) str.encode("UTF-8", :invalid => :replace, :undef => :replace) end |
.toplevel_dir ⇒ Object
123 124 125 |
# File 'lib/git_commit_notifier/git.rb', line 123 def toplevel_dir from_shell("git rev-parse --show-toplevel").strip end |