git-hub 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.kick +26 -0
- data/LICENSE +20 -0
- data/README.md +184 -0
- data/Rakefile +93 -0
- data/bin/hub +7 -0
- data/lib/hub.rb +5 -0
- data/lib/hub/args.rb +35 -0
- data/lib/hub/commands.rb +245 -0
- data/lib/hub/runner.rb +64 -0
- data/lib/hub/standalone.rb +49 -0
- data/lib/hub/version.rb +3 -0
- data/test/alias_test.rb +41 -0
- data/test/helper.rb +78 -0
- data/test/hub_test.rb +98 -0
- data/test/standalone_test.rb +46 -0
- metadata +92 -0
data/.kick
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# take control of the growl notifications
|
2
|
+
module GrowlHacks
|
3
|
+
def growl(type, subject, body, *args, &block)
|
4
|
+
case type
|
5
|
+
when Kicker::GROWL_NOTIFICATIONS[:succeeded]
|
6
|
+
puts subject = "Success"
|
7
|
+
body = body.split("\n").last
|
8
|
+
when Kicker::GROWL_NOTIFICATIONS[:failed]
|
9
|
+
subject = "Failure"
|
10
|
+
puts body
|
11
|
+
body = body.split("\n").last
|
12
|
+
else
|
13
|
+
return nil
|
14
|
+
end
|
15
|
+
super(type, subject, body, *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Kicker.send :extend, GrowlHacks
|
20
|
+
|
21
|
+
# no logging
|
22
|
+
Kicker::Utils.module_eval do
|
23
|
+
def log(message)
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Chris Wanstrath
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
hub: git + hub = github
|
2
|
+
=======================
|
3
|
+
|
4
|
+
`hub` is a command line utility which adds GitHub knowledge to `git`.
|
5
|
+
|
6
|
+
It can used on its own or as a `git` wrapper.
|
7
|
+
|
8
|
+
Normal:
|
9
|
+
|
10
|
+
$ hub clone rtomayko/tilt
|
11
|
+
Initialized empty Git repository in /Users/chris/sandbox/tilt/.git/
|
12
|
+
remote: Counting objects: 307, done.
|
13
|
+
remote: Compressing objects: 100% (219/219), done.
|
14
|
+
remote: Total 307 (delta 175), reused 85 (delta 45)
|
15
|
+
Receiving objects: 100% (307/307), 48.91 KiB, done.
|
16
|
+
Resolving deltas: 100% (175/175), done.
|
17
|
+
|
18
|
+
Wrapping `git`:
|
19
|
+
|
20
|
+
$ git clone rack/rack
|
21
|
+
Initialized empty Git repository in /Users/chris/sandbox/rack/.git/
|
22
|
+
remote: Counting objects: 4005, done.
|
23
|
+
remote: Compressing objects: 100% (1738/1738), done.
|
24
|
+
remote: Total 4005 (delta 2505), reused 3620 (delta 2208)
|
25
|
+
Receiving objects: 100% (4005/4005), 785.82 KiB | 129 KiB/s, done.
|
26
|
+
Resolving deltas: 100% (2505/2505), done.
|
27
|
+
|
28
|
+
hub requires you have `git` installed and in your path. It also
|
29
|
+
requires Ruby 1.8.6+ or Ruby 1.9.1+. No other libraries necessary.
|
30
|
+
|
31
|
+
|
32
|
+
Install
|
33
|
+
-------
|
34
|
+
|
35
|
+
### Standalone
|
36
|
+
|
37
|
+
`hub` is most easily installed as a standalone script:
|
38
|
+
|
39
|
+
curl http://defunkt.github.com/hub/standalone > ~/bin/hub && chmod 0755 !$
|
40
|
+
|
41
|
+
Assuming `~/bin/` is in your path, you're ready to roll:
|
42
|
+
|
43
|
+
$ hub version
|
44
|
+
git version 1.6.4.2
|
45
|
+
hub version 0.1.0
|
46
|
+
|
47
|
+
### Rubygems
|
48
|
+
|
49
|
+
Though not recommended, `hub` can also be installed as a Rubygem:
|
50
|
+
|
51
|
+
$ gem install git-hub -s http://gemcutter.org/
|
52
|
+
|
53
|
+
(Yes, the gem name is `git-hub`.)
|
54
|
+
|
55
|
+
### Source
|
56
|
+
|
57
|
+
You can also install from source:
|
58
|
+
|
59
|
+
$ git clone git://github.com/defunkt/hub.git
|
60
|
+
$ cd hub
|
61
|
+
$ rake standalone
|
62
|
+
$ cp hub /usr/local/bin/
|
63
|
+
|
64
|
+
|
65
|
+
Aliasing
|
66
|
+
--------
|
67
|
+
|
68
|
+
hub works best when it wraps `git`. This is not dangerous - your
|
69
|
+
normal git commands should all work. hub merely adds some sugar.
|
70
|
+
|
71
|
+
Typing `hub alias <shell>` will display alias instructions for
|
72
|
+
your shell. `hub alias` alone will show the known shells.
|
73
|
+
|
74
|
+
For example:
|
75
|
+
|
76
|
+
$ hub alias bash
|
77
|
+
Run this in your shell to start using `hub` as `git`:
|
78
|
+
alias git=hub
|
79
|
+
|
80
|
+
You should place this command in your `.bash_profile` or other startup
|
81
|
+
script to ensure runs on login.
|
82
|
+
|
83
|
+
The alias command can also be eval'd directly using the `-s` flag:
|
84
|
+
|
85
|
+
$ eval `hub alias -s bash`
|
86
|
+
|
87
|
+
|
88
|
+
Commands
|
89
|
+
--------
|
90
|
+
|
91
|
+
Assuming you've aliased `hub` to `git` the following commands now have
|
92
|
+
superpowers:
|
93
|
+
|
94
|
+
### git clone
|
95
|
+
|
96
|
+
$ git clone schacon/ticgit
|
97
|
+
> git clone git://github.com/schacon/ticgit.git
|
98
|
+
|
99
|
+
$ git clone -p schacon/ticgit
|
100
|
+
> git clone git@github.com:schacon/ticgit.git
|
101
|
+
|
102
|
+
$ git clone resque
|
103
|
+
> git clone git://github.com/YOUR_USER/resque.git
|
104
|
+
|
105
|
+
$ git clone -p resque
|
106
|
+
> git clone git@github.com:YOUR_USER/resque.git
|
107
|
+
|
108
|
+
### git remote add
|
109
|
+
|
110
|
+
$ git remote add rtomayko
|
111
|
+
> git remote add rtomayko git://github.com/rtomayko/CURRENT_REPO.git
|
112
|
+
|
113
|
+
$ git remote add -p pjhyett
|
114
|
+
> git remote add rtomayko git@github.com:rtomayko/CURRENT_REPO.git
|
115
|
+
|
116
|
+
### git init
|
117
|
+
|
118
|
+
$ git init -g
|
119
|
+
> git init
|
120
|
+
> git remote add origin git@github.com:YOUR_USER/REPO.git
|
121
|
+
|
122
|
+
### git help
|
123
|
+
|
124
|
+
$ git help
|
125
|
+
> (improved git help)
|
126
|
+
|
127
|
+
|
128
|
+
GitHub Login
|
129
|
+
------------
|
130
|
+
|
131
|
+
To get the most out of `hub`, you'll want to ensure your GitHub login
|
132
|
+
is stored locally in your Git config.
|
133
|
+
|
134
|
+
To test it run this:
|
135
|
+
|
136
|
+
$ git config --global github.user
|
137
|
+
|
138
|
+
If you see nothing, you need to set the config setting:
|
139
|
+
|
140
|
+
$ git config --global github.user YOUR_USER
|
141
|
+
|
142
|
+
See <http://github.com/guides/local-github-config> for more information.
|
143
|
+
|
144
|
+
|
145
|
+
Prior Art
|
146
|
+
---------
|
147
|
+
|
148
|
+
These projects also aim to either improve git or make interacting with
|
149
|
+
GitHub simpler:
|
150
|
+
|
151
|
+
* [eg](http://www.gnome.org/~newren/eg/)
|
152
|
+
* [github-gem](http://github.com/defunkt/github-gem)
|
153
|
+
* [gh](http://github.com/visionmedia/gh)
|
154
|
+
|
155
|
+
|
156
|
+
Contributing
|
157
|
+
------------
|
158
|
+
|
159
|
+
Once you've made your great commits:
|
160
|
+
|
161
|
+
1. [Fork][0] hub
|
162
|
+
2. Create a topic branch - `git checkout -b my_branch`
|
163
|
+
3. Push to your branch - `git push origin my_branch`
|
164
|
+
4. Create an [Issue][1] with a link to your branch
|
165
|
+
5. That's it!
|
166
|
+
|
167
|
+
|
168
|
+
Meta
|
169
|
+
----
|
170
|
+
|
171
|
+
* Code: `git clone git://github.com/defunkt/hub.git`
|
172
|
+
* Home: <http://github.com/defunkt/hub>
|
173
|
+
* Bugs: <http://github.com/defunkt/hub/issues>
|
174
|
+
* List: <http://groups.google.com/group/github>
|
175
|
+
* Gems: <http://gemcutter.org/gems/hub>
|
176
|
+
|
177
|
+
|
178
|
+
Author
|
179
|
+
------
|
180
|
+
|
181
|
+
Chris Wanstrath :: chris@ozmm.org :: @defunkt
|
182
|
+
|
183
|
+
[0]: http://help.github.com/forking/
|
184
|
+
[1]: http://github.com/defunkt/hub/issues
|
data/Rakefile
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
task :default => :test
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << 'lib'
|
7
|
+
t.pattern = 'test/**/*_test.rb'
|
8
|
+
t.verbose = false
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Launch Kicker (like autotest)"
|
12
|
+
task :kicker do
|
13
|
+
puts "Kicking... (ctrl+c to cancel)"
|
14
|
+
exec "kicker -e rake test bin"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Build a gem"
|
18
|
+
task :gem => [ :gemspec, :build ]
|
19
|
+
|
20
|
+
desc "Build standalone script"
|
21
|
+
task :standalone => [ :test, :load_hub ] do
|
22
|
+
Hub::Standalone.save('hub')
|
23
|
+
end
|
24
|
+
|
25
|
+
task :load_hub do
|
26
|
+
$LOAD_PATH.unshift 'lib'
|
27
|
+
require 'hub'
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'jeweler'
|
32
|
+
$LOAD_PATH.unshift 'lib'
|
33
|
+
require 'hub'
|
34
|
+
Jeweler::Tasks.new do |gemspec|
|
35
|
+
gemspec.name = "git-hub"
|
36
|
+
gemspec.summary = gemspec.description = "hub introduces git to GitHub"
|
37
|
+
gemspec.homepage = "http://github.com/defunkt/hub"
|
38
|
+
gemspec.version = Hub::Version
|
39
|
+
gemspec.authors = ["Chris Wanstrath"]
|
40
|
+
gemspec.email = "chris@ozmm.org"
|
41
|
+
gemspec.post_install_message = <<-message
|
42
|
+
|
43
|
+
------------------------------------------------------------
|
44
|
+
|
45
|
+
You there! Wait, I say!
|
46
|
+
=======================
|
47
|
+
|
48
|
+
If you are a heavy user of `git` on the command
|
49
|
+
line you may want to install `hub` the old
|
50
|
+
fashioned way. Faster startup time, you see.
|
51
|
+
|
52
|
+
Check out the installation instructions at
|
53
|
+
http://github.com/defunkt/hub#readme under the
|
54
|
+
"Standalone" section.
|
55
|
+
|
56
|
+
Cheers,
|
57
|
+
defunkt
|
58
|
+
|
59
|
+
------------------------------------------------------------
|
60
|
+
|
61
|
+
message
|
62
|
+
end
|
63
|
+
rescue LoadError
|
64
|
+
puts "Jeweler not available."
|
65
|
+
puts "Install it with: gem install jeweler"
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Push a new version to Gemcutter"
|
69
|
+
task :publish => [ :test, :gemspec, :build ] do
|
70
|
+
system "git tag v#{Hub::Version}"
|
71
|
+
system "git push origin v#{Hub::Version}"
|
72
|
+
system "git push origin master"
|
73
|
+
system "gem push pkg/git-hub-#{Hub::Version}.gem"
|
74
|
+
system "git clean -fd"
|
75
|
+
exec "rake pages"
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "Publish to GitHub Pages"
|
79
|
+
task :pages => [ :check_dirty, :standalone ] do
|
80
|
+
`git checkout gh-pages`
|
81
|
+
`mv hub standalone`
|
82
|
+
`git add standalone*`
|
83
|
+
`git commit -m "update standalone"`
|
84
|
+
`git push origin gh-pages`
|
85
|
+
`git checkout master`
|
86
|
+
puts :done
|
87
|
+
end
|
88
|
+
|
89
|
+
task :check_dirty do
|
90
|
+
if !`git status`.include?('nothing to commit')
|
91
|
+
abort "dirty index - not publishing!"
|
92
|
+
end
|
93
|
+
end
|
data/bin/hub
ADDED
data/lib/hub.rb
ADDED
data/lib/hub/args.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Hub
|
2
|
+
# The Args class exists to make it more convenient to work with
|
3
|
+
# command line arguments intended for git from within the Hub
|
4
|
+
# codebase.
|
5
|
+
#
|
6
|
+
# The ARGV array is converted into an Args instance by the Hub
|
7
|
+
# instance when instantiated.
|
8
|
+
class Args < Array
|
9
|
+
# With no arguments, returns the `after` callback.
|
10
|
+
#
|
11
|
+
# With a single argument, sets the `after` callback.
|
12
|
+
# Can be set to a string or a proc.
|
13
|
+
#
|
14
|
+
# If proc:
|
15
|
+
# The proc is executed after the git command is executed. For
|
16
|
+
# example, the `hub version` command sets the following proc to
|
17
|
+
# print its information after running `git version`:
|
18
|
+
#
|
19
|
+
# after { puts "hub version #{version_number}" }
|
20
|
+
#
|
21
|
+
# If string:
|
22
|
+
# The string is assumed to be a command and executed after the
|
23
|
+
# git command is executed:
|
24
|
+
#
|
25
|
+
# after "echo 'hub version #{version_number}'"
|
26
|
+
def after(command = nil, &block)
|
27
|
+
@after ||= block ? block : command
|
28
|
+
end
|
29
|
+
|
30
|
+
# Boolean indicating whether an `after` callback has been set.
|
31
|
+
def after?
|
32
|
+
!!@after
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/hub/commands.rb
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
module Hub
|
2
|
+
# The Commands module houses the git commands that hub
|
3
|
+
# lovingly wraps. If a method exists here, it is expected to have a
|
4
|
+
# corresponding git command which either gets run before or after
|
5
|
+
# the method executes.
|
6
|
+
#
|
7
|
+
# The typical flow is as follows:
|
8
|
+
#
|
9
|
+
# 1. hub is invoked from the command line:
|
10
|
+
# $ hub clone rtomayko/tilt
|
11
|
+
#
|
12
|
+
# 2. The Hub class is initialized:
|
13
|
+
# >> hub = Hub.new('clone', 'rtomayko/tilt')
|
14
|
+
#
|
15
|
+
# 3. The method representing the git subcommand is executed with the
|
16
|
+
# full args:
|
17
|
+
# >> Commands.clone('clone', 'rtomayko/tilt')
|
18
|
+
#
|
19
|
+
# 4. That method rewrites the args as it sees fit:
|
20
|
+
# >> args[1] = "git://github.com/" + args[1] + ".git"
|
21
|
+
# => "git://github.com/rtomayko/tilt.git"
|
22
|
+
#
|
23
|
+
# 5. The new args are used to run `git`:
|
24
|
+
# >> exec "git", "clone", "git://github.com/rtomayko/tilt.git"
|
25
|
+
#
|
26
|
+
# An optional `after` callback can be set. If so, it is run after
|
27
|
+
# step 5 (which then performs a `system` call rather than an
|
28
|
+
# `exec`). See `Hub::Args` for more information on the `after` callback.
|
29
|
+
module Commands
|
30
|
+
# We are a blank slate.
|
31
|
+
instance_methods.each { |m| undef_method(m) unless m =~ /(^__|send|to\?$)/ }
|
32
|
+
extend self
|
33
|
+
|
34
|
+
# Templates and useful information.
|
35
|
+
PRIVATE = 'git@github.com:%s/%s.git'
|
36
|
+
PUBLIC = 'git://github.com/%s/%s.git'
|
37
|
+
USER = `git config --global github.user`.chomp
|
38
|
+
REPO = `basename $(pwd)`.chomp
|
39
|
+
LGHCONF = "http://github.com/guides/local-github-config"
|
40
|
+
|
41
|
+
# $ hub clone rtomayko/tilt
|
42
|
+
# > git clone git://github.com/rtomayko/tilt.
|
43
|
+
#
|
44
|
+
# $ hub clone -p kneath/hemingway
|
45
|
+
# > git clone git@github.com:kneath/hemingway.git
|
46
|
+
def clone(args)
|
47
|
+
ssh = args.delete('-p')
|
48
|
+
args[1..-1].each_with_index do |arg, i|
|
49
|
+
i += 1
|
50
|
+
if arg.scan('/').size == 1 && !arg.include?(':')
|
51
|
+
url = ssh ? PRIVATE : PUBLIC
|
52
|
+
args[i] = url % arg.split('/')
|
53
|
+
break
|
54
|
+
elsif arg !~ /:|\//
|
55
|
+
url = ssh ? PRIVATE : PUBLIC
|
56
|
+
args[i] = url % [ github_user, arg ]
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# $ hub remote add pjhyett
|
63
|
+
# > git remote add pjhyett git://github.com/pjhyett/THIS_REPO.git
|
64
|
+
#
|
65
|
+
# $ hub remote add -p mojombo
|
66
|
+
# > git remote add mojombo git@github.com:mojombo/THIS_REPO.git
|
67
|
+
def remote(args)
|
68
|
+
return unless args[1] == 'add'
|
69
|
+
|
70
|
+
# Assume GitHub usernames don't ever contain : or /, while URLs
|
71
|
+
# do.
|
72
|
+
if args[-1] !~ /:|\//
|
73
|
+
ssh = args.delete('-p')
|
74
|
+
user = args.last
|
75
|
+
url = ssh ? PRIVATE : PUBLIC
|
76
|
+
args << url % [ user, REPO ]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# $ hub init -g
|
81
|
+
# > git init
|
82
|
+
# > git remote add origin git@github.com:USER/REPO.git
|
83
|
+
def init(args)
|
84
|
+
if args.delete('-g')
|
85
|
+
# Can't do anything if we don't have a USER set.
|
86
|
+
|
87
|
+
url = PRIVATE % [ github_user, REPO ]
|
88
|
+
args.after "git remote add origin #{url}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def alias(args)
|
93
|
+
shells = {
|
94
|
+
'sh' => 'alias git=hub',
|
95
|
+
'bash' => 'alias git=hub',
|
96
|
+
'zsh' => 'alias git=hub',
|
97
|
+
'csh' => 'alias git hub',
|
98
|
+
'fish' => 'alias git hub'
|
99
|
+
}
|
100
|
+
|
101
|
+
silent = args.delete('-s')
|
102
|
+
|
103
|
+
if shell = args[1]
|
104
|
+
if silent.nil?
|
105
|
+
puts "Run this in your shell to start using `hub` as `git`:"
|
106
|
+
print " "
|
107
|
+
end
|
108
|
+
else
|
109
|
+
puts "usage: hub alias [-s] SHELL", ""
|
110
|
+
puts "You already have hub installed and available in your PATH,"
|
111
|
+
puts "but to get the full experience you'll want to alias it to"
|
112
|
+
puts "`git`.", ""
|
113
|
+
puts "To see how to accomplish this for your shell, run the alias"
|
114
|
+
puts "command again with the name of your shell.", ""
|
115
|
+
puts "Known shells:"
|
116
|
+
shells.map { |key, _| key }.sort.each do |key|
|
117
|
+
puts " " + key
|
118
|
+
end
|
119
|
+
puts "", "Options:"
|
120
|
+
puts " -s Silent. Useful when using the output with eval, e.g."
|
121
|
+
puts " $ eval `hub alias -s bash`"
|
122
|
+
|
123
|
+
exit
|
124
|
+
end
|
125
|
+
|
126
|
+
if shells[shell]
|
127
|
+
puts shells[shell]
|
128
|
+
else
|
129
|
+
abort "fatal: never heard of `#{shell}'"
|
130
|
+
end
|
131
|
+
|
132
|
+
exit
|
133
|
+
end
|
134
|
+
|
135
|
+
# $ hub version
|
136
|
+
# > git version
|
137
|
+
# (print hub version)
|
138
|
+
def version(args)
|
139
|
+
args.after do
|
140
|
+
puts "hub version %s" % Version
|
141
|
+
end
|
142
|
+
end
|
143
|
+
alias_method "--version", :version
|
144
|
+
|
145
|
+
# $ hub help
|
146
|
+
# (print improved help text)
|
147
|
+
def help(args)
|
148
|
+
return if args.size > 1
|
149
|
+
puts improved_help_text
|
150
|
+
exit
|
151
|
+
end
|
152
|
+
|
153
|
+
# The text print when `hub help` is run, kept in its own method
|
154
|
+
# for the convenience of the author.
|
155
|
+
def improved_help_text
|
156
|
+
<<-help
|
157
|
+
usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]
|
158
|
+
[-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR]
|
159
|
+
[--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]
|
160
|
+
|
161
|
+
Creating a git repository:
|
162
|
+
clone Clone a repository into a new directory
|
163
|
+
init Create an empty git repository or reinitialize an existing one
|
164
|
+
|
165
|
+
Working with content:
|
166
|
+
add Add file contents to the index
|
167
|
+
branch List, create, or delete branches
|
168
|
+
checkout Checkout a branch or paths to the working tree
|
169
|
+
commit Record changes to the repository
|
170
|
+
diff Show changes between commits, commit and working tree, etc
|
171
|
+
log Show commit logs
|
172
|
+
merge Join two or more development histories together
|
173
|
+
mv Move or rename a file, a directory, or a symlink
|
174
|
+
rm Remove files from the working tree and from the index
|
175
|
+
status Show the working tree status
|
176
|
+
show Show various types of objects
|
177
|
+
tag Create, list, delete or verify a tag object signed with GPG
|
178
|
+
|
179
|
+
Over the network:
|
180
|
+
fetch Download objects and refs from another repository
|
181
|
+
pull Fetch from and merge with another repository or a local branch
|
182
|
+
push Update remote refs along with associated objects
|
183
|
+
remote Manage a set of tracked repositories
|
184
|
+
|
185
|
+
Advanced commands:
|
186
|
+
bisect Find by binary search the change that introduced a bug
|
187
|
+
grep Print lines matching a pattern
|
188
|
+
reset Reset current HEAD to the specified state
|
189
|
+
rebase Forward-port local commits to the updated upstream head
|
190
|
+
|
191
|
+
See 'git help COMMAND' for more information on a specific command.
|
192
|
+
help
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
#
|
197
|
+
# Helper methods are private so they cannot be invoked
|
198
|
+
# from the command line.
|
199
|
+
#
|
200
|
+
|
201
|
+
def github_user
|
202
|
+
if USER.empty?
|
203
|
+
abort "** No GitHub user set. See #{LGHCONF}"
|
204
|
+
else
|
205
|
+
USER
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# All calls to `puts` in after hooks or commands are paged,
|
210
|
+
# git-style.
|
211
|
+
def puts(*args)
|
212
|
+
page_stdout
|
213
|
+
super
|
214
|
+
end
|
215
|
+
|
216
|
+
# http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
|
217
|
+
def page_stdout
|
218
|
+
return unless $stdout.tty?
|
219
|
+
|
220
|
+
read, write = IO.pipe
|
221
|
+
|
222
|
+
if Kernel.fork
|
223
|
+
# Parent process, become pager
|
224
|
+
$stdin.reopen(read)
|
225
|
+
read.close
|
226
|
+
write.close
|
227
|
+
|
228
|
+
# Don't page if the input is short enough
|
229
|
+
ENV['LESS'] = 'FSRX'
|
230
|
+
|
231
|
+
# Wait until we have input before we start the pager
|
232
|
+
Kernel.select [STDIN]
|
233
|
+
|
234
|
+
pager = ENV['PAGER'] || 'less'
|
235
|
+
exec pager rescue exec "/bin/sh", "-c", pager
|
236
|
+
else
|
237
|
+
# Child process
|
238
|
+
$stdout.reopen(write)
|
239
|
+
$stderr.reopen(write) if $stderr.tty?
|
240
|
+
read.close
|
241
|
+
write.close
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
data/lib/hub/runner.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Hub
|
2
|
+
# The Hub runner expects to be initialized with `ARGV` and primarily
|
3
|
+
# exists to run a git command.
|
4
|
+
#
|
5
|
+
# The actual functionality, that is, the code it runs when it needs to
|
6
|
+
# augment a git command, is kept in the `Hub::Commands` module.
|
7
|
+
class Runner
|
8
|
+
attr_reader :args
|
9
|
+
def initialize(*args)
|
10
|
+
@args = Args.new(args)
|
11
|
+
|
12
|
+
# Hack to emulate git-style
|
13
|
+
@args[0] = 'help' if @args.empty?
|
14
|
+
|
15
|
+
if Commands.respond_to?(@args[0])
|
16
|
+
Commands.send(@args[0], @args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Shortcut
|
21
|
+
def self.execute(*args)
|
22
|
+
new(*args).execute
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the current after callback, which (if set) is run after
|
26
|
+
# the target git command.
|
27
|
+
#
|
28
|
+
# See the `Hub::Args` class for more information on the `after`
|
29
|
+
# callback.
|
30
|
+
def after
|
31
|
+
args.after.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
# A string representation of the git command we would run if
|
35
|
+
# #execute were called.
|
36
|
+
def command
|
37
|
+
"git #{args.join(' ')}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Runs the target git command with an optional callback. Replaces
|
41
|
+
# the current process.
|
42
|
+
def execute
|
43
|
+
if args.after?
|
44
|
+
execute_with_after_callback
|
45
|
+
else
|
46
|
+
exec "git", *args
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Runs the target git command then executes the `after` callback.
|
51
|
+
#
|
52
|
+
# See the `Hub::Args` class for more information on the `after`
|
53
|
+
# callback.
|
54
|
+
def execute_with_after_callback
|
55
|
+
after = args.after
|
56
|
+
if system("git", *args)
|
57
|
+
after.respond_to?(:call) ? after.call : exec(after)
|
58
|
+
exit
|
59
|
+
else
|
60
|
+
exit 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Hub
|
2
|
+
module Standalone
|
3
|
+
extend self
|
4
|
+
|
5
|
+
PREAMBLE = <<-premable
|
6
|
+
#!/usr/bin/env ruby
|
7
|
+
#
|
8
|
+
# This file, hub, is generated code.
|
9
|
+
# Please DO NOT EDIT or send patches for it.
|
10
|
+
#
|
11
|
+
# Please take a look at the source from
|
12
|
+
# http://github.com/defunkt/hub
|
13
|
+
# and submit patches against the individual files
|
14
|
+
# that build hub.
|
15
|
+
#
|
16
|
+
|
17
|
+
premable
|
18
|
+
|
19
|
+
POSTAMBLE = "Hub::Runner.execute(*ARGV)"
|
20
|
+
|
21
|
+
def save(filename, path = '.')
|
22
|
+
target = File.join(File.expand_path(path), filename)
|
23
|
+
File.open(target, 'w') do |f|
|
24
|
+
f.puts build
|
25
|
+
f.chmod 0755
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def build
|
30
|
+
root = File.dirname(__FILE__)
|
31
|
+
|
32
|
+
standalone = ''
|
33
|
+
standalone << PREAMBLE
|
34
|
+
|
35
|
+
Dir["#{root}/*.rb"].each do |file|
|
36
|
+
# skip standalone.rb
|
37
|
+
next if file == __FILE__
|
38
|
+
|
39
|
+
File.readlines(file).each do |line|
|
40
|
+
next if line =~ /^\s*#/
|
41
|
+
standalone << line
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
standalone << POSTAMBLE
|
46
|
+
standalone
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/hub/version.rb
ADDED
data/test/alias_test.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class AliasTest < Test::Unit::TestCase
|
5
|
+
def test_alias
|
6
|
+
instructions = hub("alias")
|
7
|
+
assert_includes "bash", instructions
|
8
|
+
assert_includes "sh", instructions
|
9
|
+
assert_includes "csh", instructions
|
10
|
+
assert_includes "zsh", instructions
|
11
|
+
assert_includes "fish", instructions
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_alias_silent
|
15
|
+
assert_equal "alias git=hub\n", hub("alias -s bash")
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_alias_bash
|
19
|
+
assert_alias_command "bash", "alias git=hub"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_alias_sh
|
23
|
+
assert_alias_command "sh", "alias git=hub"
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_alias_zsh
|
27
|
+
assert_alias_command "zsh", "alias git=hub"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_alias_csh
|
31
|
+
assert_alias_command "csh", "alias git hub"
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_alias_fish
|
35
|
+
assert_alias_command "fish", "alias git hub"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_alias_blah
|
39
|
+
assert_alias_command "blah", "fatal: never heard of `blah'"
|
40
|
+
end
|
41
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
+
require 'hub'
|
4
|
+
|
5
|
+
class Test::Unit::TestCase
|
6
|
+
# Shortcut for creating a `Hub` instance. Pass it what you would
|
7
|
+
# normally pass `hub` on the command line, e.g.
|
8
|
+
#
|
9
|
+
# shell: hub clone rtomayko/tilt
|
10
|
+
# test: Hub("clone rtomayko/tilt")
|
11
|
+
def Hub(args)
|
12
|
+
Hub::Runner.new(*args.split(' '))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Shortcut for running the `hub` command in a subprocess. Returns
|
16
|
+
# STDOUT as a string. Pass it what you would normally pass `hub` on
|
17
|
+
# the command line, e.g.
|
18
|
+
#
|
19
|
+
# shell: hub clone rtomayko/tilt
|
20
|
+
# test: hub("clone rtomayko/tilt")
|
21
|
+
#
|
22
|
+
# If a block is given it will be run in the child process before
|
23
|
+
# execution begins. You can use this to monkeypatch or fudge the
|
24
|
+
# environment before running hub.
|
25
|
+
def hub(args)
|
26
|
+
parent_read, child_write = IO.pipe
|
27
|
+
|
28
|
+
fork do
|
29
|
+
yield if block_given?
|
30
|
+
$stdout.reopen(child_write)
|
31
|
+
$stderr.reopen(child_write)
|
32
|
+
Hub(args).execute
|
33
|
+
end
|
34
|
+
|
35
|
+
child_write.close
|
36
|
+
parent_read.read
|
37
|
+
end
|
38
|
+
|
39
|
+
# Asserts that `hub` will run a specific git command based on
|
40
|
+
# certain input.
|
41
|
+
#
|
42
|
+
# e.g.
|
43
|
+
# assert_command "clone git/hub", "git clone git://github.com/git/hub.git"
|
44
|
+
#
|
45
|
+
# Here we are saying that this:
|
46
|
+
# $ hub clone git/hub
|
47
|
+
# Should in turn execute this:
|
48
|
+
# $ git clone git://github.com/git/hub.git
|
49
|
+
def assert_command(input, expected)
|
50
|
+
assert_equal expected, Hub(input).command
|
51
|
+
end
|
52
|
+
|
53
|
+
# Asserts that `hub` will show a specific alias command for a
|
54
|
+
# specific shell.
|
55
|
+
#
|
56
|
+
# e.g.
|
57
|
+
# assert_alias_command "sh", "alias git=hub"
|
58
|
+
#
|
59
|
+
# Here we are saying that this:
|
60
|
+
# $ hub alias sh
|
61
|
+
# Should display this:
|
62
|
+
# Run this in your shell to start using `hub` as `git`:
|
63
|
+
# alias git=hub
|
64
|
+
def assert_alias_command(shell, command)
|
65
|
+
expected = "Run this in your shell to start using `hub` as `git`:\n %s\n"
|
66
|
+
assert_equal(expected % command, hub("alias #{shell}"))
|
67
|
+
end
|
68
|
+
|
69
|
+
# Asserts that `haystack` includes `needle`.
|
70
|
+
def assert_includes(needle, haystack)
|
71
|
+
assert haystack.include?(needle)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Asserts that `haystack` does not include `needle`.
|
75
|
+
def assert_not_includes(needle, haystack)
|
76
|
+
assert !haystack.include?(needle)
|
77
|
+
end
|
78
|
+
end
|
data/test/hub_test.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class HubTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Hub::Commands::USER.replace("tpw")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_private_clone
|
10
|
+
input = "clone -p rtomayko/ron"
|
11
|
+
command = "git clone git@github.com:rtomayko/ron.git"
|
12
|
+
assert_command input, command
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_public_clone
|
16
|
+
input = "clone rtomayko/ron"
|
17
|
+
command = "git clone git://github.com/rtomayko/ron.git"
|
18
|
+
assert_command input, command
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_your_private_clone
|
22
|
+
input = "clone -p resque"
|
23
|
+
command = "git clone git@github.com:tpw/resque.git"
|
24
|
+
assert_command input, command
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_your_public_clone
|
28
|
+
input = "clone resque"
|
29
|
+
command = "git clone git://github.com/tpw/resque.git"
|
30
|
+
assert_command input, command
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_your_private_clone_fails_without_config
|
34
|
+
out = hub("clone -p mustache") do
|
35
|
+
Hub::Commands::USER.replace("")
|
36
|
+
end
|
37
|
+
|
38
|
+
assert_equal "** No GitHub user set. See http://github.com/guides/local-github-config\n", out
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_your_public_clone_fails_without_config
|
42
|
+
out = hub("clone mustache") do
|
43
|
+
Hub::Commands::USER.replace("")
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_equal "** No GitHub user set. See http://github.com/guides/local-github-config\n", out
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_private_clone_left_alone
|
50
|
+
input = "clone git@github.com:rtomayko/ron.git"
|
51
|
+
command = "git clone git@github.com:rtomayko/ron.git"
|
52
|
+
assert_command input, command
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_public_clone_left_alone
|
56
|
+
input = "clone git://github.com/rtomayko/ron.git"
|
57
|
+
command = "git clone git://github.com/rtomayko/ron.git"
|
58
|
+
assert_command input, command
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_private_remote
|
62
|
+
input = "remote add -p rtomayko"
|
63
|
+
command = "git remote add rtomayko git@github.com:rtomayko/hub.git"
|
64
|
+
assert_command input, command
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_public_remote
|
68
|
+
input = "remote add rtomayko"
|
69
|
+
command = "git remote add rtomayko git://github.com/rtomayko/hub.git"
|
70
|
+
assert_command input, command
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_init
|
74
|
+
h = Hub("init -g")
|
75
|
+
assert_equal "git init", h.command
|
76
|
+
assert_equal "git remote add origin git@github.com:tpw/hub.git", h.after
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_init_no_login
|
80
|
+
out = hub("init -g") do
|
81
|
+
Hub::Commands::USER.replace("")
|
82
|
+
end
|
83
|
+
|
84
|
+
assert_equal "** No GitHub user set. See http://github.com/guides/local-github-config\n", out
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_version
|
88
|
+
assert_equal "git version 1.6.4.2\nhub version 0.1.0\n", hub('--version')
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_help
|
92
|
+
assert_equal Hub::Commands.improved_help_text, hub("help")
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_help_by_default
|
96
|
+
assert_equal Hub::Commands.improved_help_text, hub("")
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
|
+
require 'helper'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class StandaloneTest < Test::Unit::TestCase
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
def setup
|
9
|
+
rm "hub" if File.exists? 'hub'
|
10
|
+
rm_rf "/tmp/_hub_private" if File.exists? '/tmp/_hub_private'
|
11
|
+
mkdir "/tmp/_hub_private"
|
12
|
+
chmod 0400, "/tmp/_hub_private"
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
rm "hub" if File.exists? 'hub'
|
17
|
+
rm_rf "/tmp/_hub_private" if File.exists? "/tmp/_hub_private"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_standalone
|
21
|
+
standalone = Hub::Standalone.build
|
22
|
+
assert_includes "This file, hub, is generated code", standalone
|
23
|
+
assert_includes "Runner", standalone
|
24
|
+
assert_includes "Args", standalone
|
25
|
+
assert_includes "Commands", standalone
|
26
|
+
assert_includes ".execute(*ARGV)", standalone
|
27
|
+
assert_not_includes "module Standalone", standalone
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_standalone_save
|
31
|
+
Hub::Standalone.save("hub")
|
32
|
+
assert_equal Hub::Standalone.build + "\n", File.read('./hub')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_standalone_save_permission_denied
|
36
|
+
assert_raises Errno::EACCES do
|
37
|
+
Hub::Standalone.save("hub", "/tmp/_hub_private")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_standalone_save_doesnt_exist
|
42
|
+
assert_raises Errno::ENOENT do
|
43
|
+
Hub::Standalone.save("hub", "/tmp/something/not/real")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-hub
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Wanstrath
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-08 00:00:00 -08:00
|
13
|
+
default_executable: hub
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: hub introduces git to GitHub
|
17
|
+
email: chris@ozmm.org
|
18
|
+
executables:
|
19
|
+
- hub
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
files:
|
26
|
+
- .kick
|
27
|
+
- LICENSE
|
28
|
+
- README.md
|
29
|
+
- Rakefile
|
30
|
+
- bin/hub
|
31
|
+
- lib/hub.rb
|
32
|
+
- lib/hub/args.rb
|
33
|
+
- lib/hub/commands.rb
|
34
|
+
- lib/hub/runner.rb
|
35
|
+
- lib/hub/standalone.rb
|
36
|
+
- lib/hub/version.rb
|
37
|
+
- test/alias_test.rb
|
38
|
+
- test/helper.rb
|
39
|
+
- test/hub_test.rb
|
40
|
+
- test/standalone_test.rb
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/defunkt/hub
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message: |+
|
46
|
+
|
47
|
+
------------------------------------------------------------
|
48
|
+
|
49
|
+
You there! Wait, I say!
|
50
|
+
=======================
|
51
|
+
|
52
|
+
If you are a heavy user of `git` on the command
|
53
|
+
line you may want to install `hub` the old
|
54
|
+
fashioned way. Faster startup time, you see.
|
55
|
+
|
56
|
+
Check out the installation instructions at
|
57
|
+
http://github.com/defunkt/hub#readme under the
|
58
|
+
"Standalone" section.
|
59
|
+
|
60
|
+
Cheers,
|
61
|
+
defunkt
|
62
|
+
|
63
|
+
------------------------------------------------------------
|
64
|
+
|
65
|
+
rdoc_options:
|
66
|
+
- --charset=UTF-8
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 1.3.5
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: hub introduces git to GitHub
|
88
|
+
test_files:
|
89
|
+
- test/alias_test.rb
|
90
|
+
- test/helper.rb
|
91
|
+
- test/hub_test.rb
|
92
|
+
- test/standalone_test.rb
|