git-multi 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8ab3d13fb8baa05e875b2bc7139802bff606cab488e33bc59ece66f58cdaad6f
4
+ data.tar.gz: 88447dad2a38f602c07d4c0e61633669cfbffbc4fb85c14d7f2ecf5e0a5974bd
5
+ SHA512:
6
+ metadata.gz: 6d0eab7a6c0ae9d59c8f4618b4c855012db420561a7a21eb9b145a1b4e12e643b957bd54584f7939d755419ffc1a3caecad3e5345223e1a52ecde0499c27bc97
7
+ data.tar.gz: 7f887eac42a5f845203753b9e3cd7d1990250fac70adb98c478dffa85456a1eb1ba369c1bdbc9c7055ae09ad235e141c683def563f970383445d0bd31e0a60bd
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.pryrc ADDED
@@ -0,0 +1,39 @@
1
+ # this loads all of "git-multi"
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'git/multi'
5
+
6
+ # this loads all "git multi" contribs
7
+ Dir.glob File.join(__dir__, 'contrib', '*', '*.rb'), &method(:require)
8
+
9
+ # configure a logger
10
+ require 'logger'
11
+ logger = Logger.new(STDOUT)
12
+ logger.level = Logger::INFO
13
+
14
+ # configure Octokit middleware with logger
15
+ require 'octokit'
16
+ Octokit.middleware.response :logger, logger
17
+
18
+ # enumerator for Faraday middleware apps
19
+ def (middleware = Octokit.middleware).each_app
20
+ Enumerator.new do |yielder|
21
+ next_app = app
22
+ while next_app do
23
+ yielder << next_app
24
+ next_app = next_app.instance_variable_get(:@app)
25
+ end
26
+ end
27
+ end
28
+
29
+ # utility function to set pry context
30
+ # to an instance of <Octokit::Client>
31
+ def client() pry Git::Hub.send(:client) ; end
32
+
33
+ # utility function to set pry context
34
+ # to the Array of github repositories
35
+ def repos() pry Git::Multi.repositories ; end
36
+
37
+ # utility function to set pry context
38
+ # to the various 'git multi' commands:
39
+ def cmds() pry Git::Multi::Commands ; end
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ Style/FrozenStringLiteralComment:
2
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.1
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in git-multi.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Peter Vandenberk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # `git-multi`
2
+
3
+ ## Summary
4
+
5
+ Execute the same `git` command in a set of related repos.
6
+
7
+ There are plenty of other utilities out there that do something similar, but typically they only support a limited number of hard-coded `git` commands which can be executed in multiple repositories.
8
+
9
+ `git-multi` is different: any `git` command _(including any `git` extensions you may have installed or any `git` aliases you may have defined)_ can be executed in multiple repositories.
10
+
11
+ `git-multi` only concerns itself with iterating over the set of related repos; what it executes in each of them is completely up to you.
12
+
13
+ ## Features
14
+
15
+ * execute any `git` command, extension and alias in multiple repositories _(not just a limited set of pre-packaged commands)_
16
+ * human-friendly output in interactive mode _(akin to [git porcelain][p-p] commands)_, for every day use
17
+ * machine parseable output in non-interactive mode _(akin to [git plumbing][p-p] commands)_, for advanced scripting and automation
18
+
19
+ [p-p]: https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain
20
+
21
+ ## Prerequisites
22
+
23
+ `git-multi` is a Ruby script, so you will have to have Ruby installed on your system _(system Ruby, [RVM][], [rbenv][], etc)_.
24
+
25
+ `git-multi` is also tightly coupled to your [GitHub][] account _(via the github API)_, so you will also need to generate a so-called [personal access token][token] and install it in your git config _(instructions provided below)_.
26
+
27
+ [rvm]: https://rvm.io
28
+ [rbenv]: http://rbenv.org
29
+ [github]: https://github.com
30
+ [token]: https://github.com/settings/tokens
31
+
32
+ ## Installation
33
+
34
+ $ gem install git-multi
35
+
36
+ ## Usage
37
+
38
+ $ git multi --help
39
+
40
+ ## Known Issues
41
+
42
+ 1. it probably doesn't work on Windows
43
+
44
+ ## Contributing
45
+
46
+ 1. Fork it ( https://github.com/pvdb/git-multi/fork )
47
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
48
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
49
+ 4. Push to the branch (`git push origin my-new-feature`)
50
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ def gemspec
4
+ @gemspec ||= begin
5
+ # rubocop:disable Security/Eval
6
+ eval(File.read('git-multi.gemspec'))
7
+ # rubocop:enable Security/Eval
8
+ end
9
+ end
10
+
11
+ desc 'Validate the gemspec'
12
+ task :validate do
13
+ gemspec.validate
14
+ end
15
+
16
+ require 'rake/testtask'
17
+
18
+ Rake::TestTask.new(:test) do |t|
19
+ t.libs << 'test'
20
+ t.libs << 'lib'
21
+ t.test_files = FileList['test/**/*_test.rb']
22
+ end
23
+
24
+ # rubocop:disable Style/HashSyntax
25
+
26
+ task :default => :test
27
+
28
+ # rubocop:enable Style/HashSyntax
data/bin/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'git/multi'
5
+
6
+ require 'pry'
7
+ Pry.start
8
+
9
+ # That's all Folks!
data/bin/setup ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ rbenv install -s
7
+ gem install --conservative bundler
8
+ bundle install
9
+
10
+ set +vxeu
11
+ echo
12
+
13
+ # That's all Folks!
@@ -0,0 +1,35 @@
1
+ <div style="font-family: monospace;">
2
+ <% @projects.each do |project| %>
3
+ <div style="float: left; width: 390px; margin: 10px;">
4
+ <table border="1" style="border: 1px solid black; width: 100%; padding: 5px;" summary="<%= project.full_name %>">
5
+ <tr>
6
+ <th style="text-align: center; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
7
+ <a href="<%= project.html_url %>" style="color: inherit; text-decoration: none;">
8
+ <%= project.full_name %>
9
+ </a>
10
+ </th>
11
+ </tr>
12
+ <tr>
13
+ <td>
14
+ <strong>Last commit &hellip;</strong>
15
+ </td>
16
+ </tr>
17
+ <tr>
18
+ <td style="text-align: right; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
19
+ <span title="<%= project.pushed_at %>">
20
+ <%= project.age_in_words %> ago
21
+ </span>
22
+ </td>
23
+ </tr>
24
+ <% TIME_INTERVALS.each_pair do |interval_name, interval_in_seconds| %>
25
+ <% in_interval = (project.age_in_seconds <= interval_in_seconds) %>
26
+ <tr style="border: 1px solid black; background-color: <%= in_interval ? GREEN[interval_name] : RED[interval_name] %>;">
27
+ <td style="color: white; padding-left: 20px;">
28
+ &hellip; in the previous <%= interval_name %>
29
+ </td>
30
+ </tr>
31
+ <% end %>
32
+ </table>
33
+ </div>
34
+ <% end %>
35
+ </div>
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ TIME_INTERVALS = {
4
+
5
+ :minute => ( MINUTE = 60 ), # seconds
6
+ :hour => ( HOUR = 60 * MINUTE ),
7
+ :day => ( DAY = 24 * HOUR ),
8
+ :week => ( WEEK = 7 * DAY ),
9
+ :year => ( YEAR = 365 * DAY ),
10
+ :month => ( MONTH = YEAR / 12 ),
11
+ :quarter => ( QUARTER = YEAR / 4 ),
12
+
13
+ }.delete_if { |key, _| key == :minute }.sort_by(&:last).to_h.freeze
14
+
15
+ def time_distance_in_words(seconds)
16
+ case
17
+ when seconds < HOUR then "less than an hour"
18
+ when seconds < DAY then "about #{(seconds / HOUR).round} hour(s)"
19
+ when seconds < MONTH then "about #{(seconds / DAY).round} day(s)"
20
+ when seconds < QUARTER then "about #{(seconds / WEEK).round} week(s)"
21
+ when seconds < YEAR then "about #{(seconds / MONTH).round} month(s)"
22
+ else "about #{(seconds / YEAR).round} year(s)"
23
+ end
24
+ end
25
+
26
+ BLUE = {
27
+ :hour => "#CCCCFF" ,
28
+ :day => "#AAAAFF" ,
29
+ :week => "#8888FF" ,
30
+ :month => "#6666FF" ,
31
+ :quarter => "#4444FF" ,
32
+ :year => "#2222FF" ,
33
+ }.freeze
34
+
35
+ GREEN = {
36
+ :hour => "#CCFFCC" ,
37
+ :day => "#AAFFAA" ,
38
+ :week => "#88FF88" ,
39
+ :month => "#66FF66" ,
40
+ :quarter => "#44FF44" ,
41
+ :year => "#22FF22" ,
42
+ }.freeze
43
+
44
+ RED = {
45
+ :hour => "#FFCCCC" ,
46
+ :day => "#FFAAAA" ,
47
+ :week => "#FF8888" ,
48
+ :month => "#FF6666" ,
49
+ :quarter => "#FF4444" ,
50
+ :year => "#FF2222" ,
51
+ }.freeze
52
+
53
+ if __FILE__ == $0
54
+
55
+ $:.unshift File.expand_path('../../lib', __dir__)
56
+
57
+ require 'git/multi'
58
+
59
+ # get list of GitHub repositories:
60
+ @projects = Git::Multi.repositories
61
+
62
+ # annotate the list of projects
63
+ @projects.each do |project|
64
+ def project.age_in_seconds
65
+ (Time.now - pushed_at).to_i
66
+ end
67
+ def project.age_in_words
68
+ time_distance_in_words(age_in_seconds)
69
+ end
70
+ end
71
+
72
+ # reverse-order based on the last commit
73
+ @projects.sort_by!(&:pushed_at).reverse!
74
+
75
+ require 'erb'
76
+
77
+ # generate HTML page with a dashboard of global GitHub repository activity:
78
+ puts ERB.new(File.read(File.join(__dir__, "git-dash.erb"))).result(binding)
79
+
80
+ end
81
+
82
+ # That's all Folks!
data/doc/git-multi.man ADDED
@@ -0,0 +1,143 @@
1
+ GIT-META(1) Git Extensions GIT-META(1)
2
+
3
+ NAME
4
+ git-multi -- execute the same git command in multiple repositories
5
+
6
+
7
+ SYNOPSIS
8
+ git multi <some_git_command_with_relevant_arguments>
9
+
10
+ DESCRIPTION
11
+ Convenient way to execute the same git command in a set of related repos,
12
+ currently the list of an organization's repositories on Github.
13
+
14
+ Said list is determined via a Github API v3 call, and cached locally for
15
+ performance.
16
+
17
+ OPTIONS
18
+
19
+ git multi --help # you're looking at it
20
+ git multi --check # checks all the required settings and configurations
21
+ git multi --version # print out this script's version number
22
+ git multi --refresh # refresh the list of organization repos
23
+ git multi --json # output repository details to JSON
24
+ git multi --count # print out the count of organization repos (per type)
25
+ git multi --list # print out the names of all organization repos
26
+ git multi --archived # print out the names of all organization repos
27
+ git multi --forked # print out the names of all organization repos
28
+ git multi --private # print out the names of all organization repos
29
+ git multi --paths # print out the full path for each organization repos
30
+ git multi --spurious # list cloned repos whose remote doesn't match a github.com origin
31
+ git multi --missing # print out names of repos that haven't been cloned
32
+ git multi --stale # list repos that have been deleted on github.com
33
+ git multi --excess # list repos that don't exist on github.com
34
+ git multi --clone # clones missing repositories into "${HOME}/Workarea" (by default)
35
+ git multi --query (args) # query Github repo multidata for each repository
36
+ git multi --find <ruby> # print out the repos for which the Ruby code evaluates to true
37
+ git multi --eval <ruby> # execute the given Ruby code in the context of each repo
38
+ get multi --raw <cmd> # execute the given shell command inside each git repository
39
+
40
+ EXAMPLES
41
+
42
+ # count the number of organization repos
43
+ git multi --list | wc -l
44
+
45
+ # disk usage of each locally cloned organization repo
46
+ git multi --paths | xargs -n 1 du -hs
47
+
48
+ # ... or by using the `--raw` option
49
+ git multi --raw 'du -hs .'
50
+
51
+ # group and count the repos by Github-determined language
52
+ git multi --query language | cut -f 2 -d : | sort | uniq -c | sort -n -r
53
+
54
+ # find out the most-used Ruby versions
55
+ git multi --raw '[ -f .ruby-version ] && cat .ruby-version' | cut -f 2 -d : | sort | uniq -c | sort -n -r
56
+
57
+ # find Github repos without a description
58
+ git multi --query description | egrep ': *$'
59
+
60
+ # fetch remote branches for all organization repos
61
+ git multi fetch -p
62
+
63
+ # print out the local branch for each repo
64
+ git multi rev-parse --abbrev-ref=strict HEAD
65
+
66
+ # find all repos for which the 'origin' remote isn't github.com
67
+ git multi config --get remote.origin.url | fgrep -v git@github.com:
68
+
69
+ # a kind of "repository creation" report: count the number of repos created in each quarter
70
+ git multi --eval "class ::Time; def quarter() (month.to_f / 3.0).ceil; end; end; puts format('%%d-Q%%d', created_at.year, created_at.quarter)" | sort | uniq -c
71
+
72
+ # for each repo, list all remote branches, sorted by the "age" of the last commit on each branch
73
+ git multi for-each-ref --sort="-authordate" --format="%%(refname)%%09%%(authordate:relative)%%09%%(authorname)" refs/remotes/origin
74
+
75
+ # same as above, but columnize the generated output (NOTE: replace '^I' with CTRL-V/CTRL-I in your terminal)
76
+ git multi for-each-ref --sort="-authordate" --format="%%(refname)%%09%%(authordate:relative)%%09%%(authorname)" refs/remotes/origin | column -t -s "^I"
77
+
78
+ # same as above, but refresh the list of remote branches first
79
+ git multi fetch -p ; git multi for-each-ref --sort="-authordate" --format="%%(refname)%%09%%(authordate:relative)%%09%%(authorname)" refs/remotes/origin
80
+
81
+ # find all organization repositories that depend on a given org repo, e.g. 'business_rules'
82
+ git multi --graph | fgrep business_rules
83
+
84
+ # find all Rails projects
85
+ git multi --raw '[ -f Gemfile ] && fgrep -q -l rails Gemfile && echo uses Rails' | cat
86
+
87
+ # find all Mongoid dependencies
88
+ git multi --raw '[ -f Gemfile.lock ] && egrep -i "^ mongoid (.*)" Gemfile.lock' | column -s: -t
89
+
90
+ # find all projects that have been pushed to in the last week
91
+ git multi --find '((Time.now - pushed_at) / 60 / 60 / 24) <= 7'
92
+
93
+ # print out the number of days since the last push to each repository
94
+ git multi --eval 'puts "%%d days" %% ((Time.now - pushed_at) / 60 / 60 / 24)'
95
+
96
+ # find all projects that have seen activity this calendar year
97
+ git multi --find 'pushed_at >= Date.civil(Date.today.year, 1, 1).to_time'
98
+
99
+ # print out all webhooks
100
+ git multi --eval '(hooks = client.hooks(project.full_name)).any? && begin print project.full_name ; print "\t" ; puts hooks.map { |hook| ["", hook.name, hook.config.url].join("\t") } ; end'
101
+
102
+ # print out all deploy keys
103
+ git multi --eval '(keys = client.list_deploy_keys(project.full_name)).any? && begin print project.full_name ; print "\t" ; puts keys.map(&:title).sort.join("\t") ; end'
104
+
105
+ # generate a dependency graph of all organization repositories using yuml.me
106
+ DEPENDENCIES=$( git multi --graph | ruby -n -e 'parent, children = $_.split(": ") ; puts children.split(" ").map { |child| "[#{parent}]->[#{child}]" }' | tr '\n' ',' ) ; open "http://yuml.me/diagram/scruffy/class/${DEPENDENCIES}"
107
+
108
+ # generate a dependency graph of all organization repositories using Graphviz
109
+ git multi --graph | ruby -n -e 'parent, children = $_.split(": ") ; puts children.split(" ").map { |child| "\"#{parent}\"->\"#{child}\";" }' | awk 'BEGIN { print "digraph {\nrankdir=\"LR\";\n" } ; { print ; } END { print "}\n" } ; ' | dot -Tpng > /tmp/ghor.png ; open -a Preview /tmp/ghor.png
110
+
111
+ QUERY ARGUMENTS
112
+
113
+ The following is a list of valid arguments for the 'git multi --query' option
114
+
115
+ %{query_args}
116
+
117
+ USE `jq` TO QUERY THE `git multi` CACHE
118
+
119
+ `jq` is like `sed` for JSON data... all of the above query arguments can be
120
+ used in conjunction with `jq` to query, filter, map and transform the github
121
+ repository attributes stored in `${HOME}/.gitmulti.byte`
122
+
123
+ EXAMPLES
124
+
125
+ # print out each repository's name and its description
126
+ git multi --json | jq '.[] | .name + ": " + .description'
127
+
128
+ # print out the name of all "forked" repositories
129
+ git multi --json | jq '.[] | select(.fork == true) | .full_name'
130
+
131
+ FILES
132
+
133
+ ${HOME}/Workarea # root directory where organization repos have been cloned
134
+
135
+ REFERENCES
136
+
137
+ # the Github API call used to refresh the list of organization repos
138
+ http://developer.github.com/v3/orgs/teams/#list-team-repos
139
+
140
+ # the `jq` command-line utility
141
+ http://stedolan.github.io/jq/
142
+
143
+ git-multi %{version} 1 March 2015 GIT-META(1)
data/exe/git-multi ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'git/multi'
6
+
7
+ case (command = ARGV.shift)
8
+ when /\A--/
9
+ case command
10
+ when '--help' then Git::Multi::Commands.help
11
+ when '--check' then Git::Multi::Commands.check
12
+ when '--version' then Git::Multi::Commands.version
13
+ when '--refresh' then Git::Multi::Commands.refresh
14
+ when '--json' then Git::Multi::Commands.json
15
+ when '--count' then Git::Multi::Commands.count
16
+ when '--list' then Git::Multi::Commands.list
17
+ when '--archived'then Git::Multi::Commands.archived
18
+ when '--forked' then Git::Multi::Commands.forked
19
+ when '--private' then Git::Multi::Commands.private
20
+ when '--paths' then Git::Multi::Commands.paths
21
+ when '--spurious'then Git::Multi::Commands.spurious
22
+ when '--missing' then Git::Multi::Commands.missing
23
+ when '--stale' then Git::Multi::Commands.stale
24
+ when '--excess' then Git::Multi::Commands.excess
25
+ when '--clone' then Git::Multi::Commands.clone
26
+ when '--query' then Git::Multi::Commands.query(ARGV)
27
+ when '--find' then Git::Multi::Commands.find(ARGV)
28
+ when '--eval' then Git::Multi::Commands.eval(ARGV)
29
+ when '--raw' then Git::Multi::Commands.raw(ARGV)
30
+ else
31
+ abort \
32
+ "Unknown 'git multi' command: #{command}\n\n" \
33
+ "(use --help/-h to list all available commands)"
34
+ end
35
+ when nil, '', '-h'
36
+ Git::Multi::Commands.help
37
+ else
38
+ Git::Multi::Commands.report
39
+ Git::Multi::Commands.exec command, ARGV
40
+ end
41
+
42
+ # That's all Folks!
data/git-multi.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'git/multi/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = Git::Multi::NAME
7
+ spec.version = Git::Multi::VERSION
8
+ spec.authors = ['Peter Vandenberk']
9
+ spec.email = ['pvandenberk@mac.com']
10
+
11
+ spec.summary = 'The ultimate multi-repo utility for git!'
12
+ spec.description = 'Run the same git command in a set of related repos'
13
+ spec.homepage = 'https://github.com/pvdb/git-multi'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = begin
17
+ `git ls-files -z`
18
+ .split("\x0")
19
+ .reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = 'exe'
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.post_install_message = Git::Multi::PIM
26
+
27
+ spec.add_dependency 'octokit', '~> 4.12'
28
+
29
+ spec.add_development_dependency 'bundler'
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'rake'
32
+ end
@@ -0,0 +1,11 @@
1
+ class Numeric
2
+ def commify
3
+ to_s.commify
4
+ end
5
+ end
6
+
7
+ class String
8
+ def commify
9
+ gsub(/(\d)(?=(\d{3})+(\..*)?$)/,'\1,')
10
+ end
11
+ end
data/lib/ext/dir.rb ADDED
@@ -0,0 +1,10 @@
1
+ class Dir
2
+ def git_repos(subdir = '*')
3
+ Dir.glob(File.join(self.path, subdir, '*', '.git')).map { |path_to_git_dir|
4
+ path_to_git_repo = File.dirname(path_to_git_dir) # without "/.git"
5
+ repo_name = path_to_git_repo[/[^\/]+\/[^\/]+\z/] # e.g. "pvdb/git-multi"
6
+ def repo_name.full_name() self ; end # awesome duck-typing!
7
+ repo_name
8
+ }
9
+ end
10
+ end
data/lib/ext/notify.rb ADDED
@@ -0,0 +1,20 @@
1
+ begin
2
+ require 'terminal-notifier'
3
+ rescue LoadError
4
+ # NOOP - "TerminalNotifier" is optional
5
+ # will only be used if it is installed!
6
+ end
7
+
8
+ def notify(message, options = {}, verbose = false)
9
+ # print the given message to STDERR, if the
10
+ # script is running with "--verbose" option
11
+ subtitle = options[:subtitle]
12
+ warn(subtitle ? "#{subtitle}: #{message}" : message) if $VERBOSE
13
+ # send a given message to the Mac OS X Notification Center
14
+ # but only if the git-multi script is running interactively
15
+ # and if the "terminal-notifier" gem has been installed...
16
+ if $INTERACTIVE && defined?(TerminalNotifier)
17
+ options[:title] ||= 'git-multi'
18
+ TerminalNotifier.notify(message, options, verbose)
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Sawyer
2
+ class Resource
3
+ def to_json(*args) to_h.to_json(args) ; end
4
+ end
5
+ end
data/lib/ext/string.rb ADDED
@@ -0,0 +1,14 @@
1
+ class String
2
+
3
+ def colorize(color_code) "\e[#{color_code}m#{self}\e[0m" ; end
4
+
5
+ def bold() colorize('1') ; end
6
+ def invert() colorize('7') ; end
7
+
8
+ def red() colorize('31') ; end
9
+ def blue() colorize('34') ; end
10
+ def green() colorize('32') ; end
11
+
12
+ def undent() gsub(/^.{#{slice(/^ +/).length}}/, '') ; end
13
+
14
+ end
data/lib/ext/utils.rb ADDED
@@ -0,0 +1,31 @@
1
+ $INTERACTIVE = (STDOUT.tty? && STDERR.tty?)
2
+
3
+ def git_option name, default = nil
4
+ value = `git config #{name}`.chomp.freeze
5
+ value.empty? && default ? default : value
6
+ end
7
+
8
+ def env_var name, default = nil
9
+ value = ENV[name].freeze
10
+ (value.nil? || value.empty?) && default ? default : value
11
+ end
12
+
13
+ def describe token
14
+ token.nil? ? '(nil)' : token.empty? ? '(empty)' : "#{'*'*36}#{token[36..-1]}"
15
+ end
16
+
17
+ def symbolize token
18
+ case token
19
+ when env_var('OCTOKIT_ACCESS_TOKEN') then '${OCTOKIT_ACCESS_TOKEN}'
20
+ when git_option('github.token') then 'github.token'
21
+ else '(unset)'
22
+ end
23
+ end
24
+
25
+ def abbreviate directory, root_dir = nil
26
+ case root_dir
27
+ when :home then directory.gsub(Git::Multi::HOME, '${HOME}')
28
+ when :workarea then directory.gsub(Git::Multi::WORKAREA, '${WORKAREA}')
29
+ else abbreviate(abbreviate(directory, :workarea), :home)
30
+ end
31
+ end