webmat-git_remote_branch 0.2.4 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +17 -0
- data/COPYING +18 -0
- data/README +39 -13
- data/Rakefile +2 -41
- data/TODO +8 -12
- data/bin/grb +10 -3
- data/lib/git_remote_branch.rb +62 -24
- data/lib/param_reader.rb +54 -22
- data/lib/version.rb +14 -0
- data/tasks/gem.rake +73 -0
- data/tasks/test.rake +21 -0
- data/test/functional/grb_test.rb +154 -0
- data/test/helpers/array_extensions.rb +14 -0
- data/test/helpers/dir_stack.rb +25 -0
- data/test/helpers/extractable.rb +63 -0
- data/test/helpers/git_helper.rb +33 -0
- data/test/helpers/more_assertions.rb +16 -0
- data/test/helpers/shoulda_functional_helpers.rb +106 -0
- data/test/helpers/shoulda_unit_helpers.rb +88 -0
- data/test/helpers/temp_dir_helper.rb +38 -0
- data/test/test_helper.rb +16 -8
- data/test/unit/git_remote_branch_test.rb +39 -0
- data/test/unit/param_reader_test.rb +261 -0
- data/vendor/capture_fu.rb +58 -0
- metadata +46 -8
- data/test/git_helper.rb +0 -57
data/CHANGELOG
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
* Release 0.2.6 *
|
2
|
+
Three new actual features
|
3
|
+
- grb rename, contributed by Caio Chassot (caiochassot.com)
|
4
|
+
- grb publish, to make available and track a local branch
|
5
|
+
- the --silent option, if you want to use grb in a script
|
6
|
+
|
7
|
+
And other stuff
|
8
|
+
- the grb bin file now works when symlinked (also thanks to Caio Chassot)
|
9
|
+
- Lots and lots of unit and functional tests
|
10
|
+
- bug fixes
|
11
|
+
- more flexibility for running grb outside of a git repository (e.g. for 'explain' or 'help')
|
12
|
+
- Now officially under the MIT license
|
13
|
+
- refactored a bunch of rake tasks
|
14
|
+
|
15
|
+
|
16
|
+
Versions lost in time:
|
17
|
+
0.2.1, 0.2.2, 0.2.3, 0.2.4
|
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2008 Mathieu Martin
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
@@ -13,12 +13,16 @@ commands. Each operation done on your behalf is displayed at the console.
|
|
13
13
|
|
14
14
|
==== Installation ====
|
15
15
|
|
16
|
-
sudo gem install
|
16
|
+
sudo gem install grb
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
http://
|
18
|
+
|
19
|
+
Or if you want the bleeding edge from GitHub
|
20
|
+
You may try
|
21
|
+
sudo gem install webmat-git_remote_branch --source=http://gems.github.com
|
22
|
+
|
23
|
+
But you're probably better off with
|
24
|
+
git clone git://github.com/webmat/git_remote_branch.git
|
25
|
+
rake install
|
22
26
|
|
23
27
|
|
24
28
|
|
@@ -30,9 +34,10 @@ Notes:
|
|
30
34
|
|
31
35
|
Available commands (with aliases):
|
32
36
|
|
37
|
+
|
33
38
|
== Help ==
|
34
39
|
|
35
|
-
$ grb [-h] #=> Displays help
|
40
|
+
$ grb [-h|help] #=> Displays help
|
36
41
|
|
37
42
|
== create (alias: new) ==
|
38
43
|
Create a new local branch as well as a corresponding remote branch from the
|
@@ -43,6 +48,14 @@ Switch to the new branch.
|
|
43
48
|
$ grb create branch_name [origin_server]
|
44
49
|
|
45
50
|
|
51
|
+
== publish (aliases: remotize) ==
|
52
|
+
Publish an existing local branch to the remote server.
|
53
|
+
Set up the local branch to track the new remote branch.
|
54
|
+
Switch to the new branch.
|
55
|
+
|
56
|
+
$ grb publish branch_name [origin_server]
|
57
|
+
|
58
|
+
|
46
59
|
== delete (aliases: destroy, kill, remove) ==
|
47
60
|
Delete the remote branch then delete the local branch.
|
48
61
|
The local branch is not deleted if there are pending changes.
|
@@ -57,10 +70,10 @@ $ grb track branch_name [origin_server]
|
|
57
70
|
|
58
71
|
|
59
72
|
== rename (aliases: rn, mv, move) ==
|
60
|
-
|
61
|
-
|
62
|
-
with the
|
63
|
-
|
73
|
+
To rename the branch you're currently on.
|
74
|
+
Rename the remote branch by copying then deleting the old name.
|
75
|
+
Checkout a new local tracking branch with the new name and delete the local
|
76
|
+
branch with the old name.
|
64
77
|
|
65
78
|
$ grb rename branch_name [origin_server]
|
66
79
|
|
@@ -73,7 +86,7 @@ run to accomplish that goal.
|
|
73
86
|
Examples:
|
74
87
|
|
75
88
|
$ grb explain create
|
76
|
-
git_remote_branch version 0.2.
|
89
|
+
git_remote_branch version 0.2.6
|
77
90
|
|
78
91
|
List of operations to do to create a new remote branch and track it locally:
|
79
92
|
|
@@ -84,7 +97,7 @@ git checkout branch_to_create
|
|
84
97
|
|
85
98
|
|
86
99
|
$ grb explain create my_branch github
|
87
|
-
git_remote_branch version 0.2.
|
100
|
+
git_remote_branch version 0.2.6
|
88
101
|
|
89
102
|
List of operations to do to create a new remote branch and track it locally:
|
90
103
|
|
@@ -94,6 +107,14 @@ git branch --track my_branch github/my_branch
|
|
94
107
|
git checkout my_branch
|
95
108
|
|
96
109
|
|
110
|
+
|
111
|
+
==== More on git_remote_branch ====
|
112
|
+
|
113
|
+
Site: http://github.com/webmat/git_remote_branch
|
114
|
+
Mailing list: http://groups.google.com/group/git_remote_branch
|
115
|
+
|
116
|
+
|
117
|
+
|
97
118
|
==== History ====
|
98
119
|
|
99
120
|
This script was originally created by Carl Mercier and made public on his blog
|
@@ -107,8 +128,13 @@ I'm using it as a starting point to make it even easier to interact with remote
|
|
107
128
|
repositories.
|
108
129
|
|
109
130
|
|
110
|
-
|
131
|
+
== Contributors ==
|
111
132
|
|
112
133
|
- Mathieu Martin webmat@gmail.com
|
113
134
|
- Carl Mercier (Carl: want your email here?)
|
114
135
|
- Caio Chassot dev@caiochassot.com
|
136
|
+
|
137
|
+
|
138
|
+
== Legalese ==
|
139
|
+
|
140
|
+
git_remote_branch is licensed under the MIT License. See the file COPYING for details.
|
data/Rakefile
CHANGED
@@ -1,51 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
require 'rake'
|
4
|
-
require 'rake/testtask'
|
5
|
-
require 'rake/gempackagetask'
|
6
4
|
|
7
5
|
HERE = File.dirname(__FILE__)
|
8
|
-
|
9
|
-
require "#{HERE}/lib/git_remote_branch"
|
10
|
-
|
11
|
-
|
12
|
-
#Stuff gleaned from merb-core's Rakefile
|
13
|
-
NAME = 'git_remote_branch'
|
14
6
|
windows = (RUBY_PLATFORM =~ /win32|cygwin/) rescue nil
|
15
|
-
install_home = ENV['GEM_HOME'] ? "-i #{ENV['GEM_HOME']}" : ""
|
16
7
|
SUDO = windows ? "" : "sudo"
|
17
8
|
|
18
|
-
|
19
|
-
|
20
|
-
t.pattern = 'test/**/*_test.rb'
|
21
|
-
t.verbose = true
|
22
|
-
end
|
9
|
+
require "#{HERE}/lib/git_remote_branch"
|
10
|
+
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
23
11
|
|
24
12
|
task :default => :test
|
25
|
-
|
26
|
-
gem_spec = eval(File.read("#{HERE}/git_remote_branch.gemspec"))
|
27
|
-
|
28
|
-
namespace :gem do
|
29
|
-
#Creates clobber_package, gem, package, repackage tasks
|
30
|
-
#Note on clobber_package: fortunately, this will clobber the CODE package
|
31
|
-
Rake::GemPackageTask.new(gem_spec) do |pkg|
|
32
|
-
pkg.need_tar = true
|
33
|
-
end
|
34
|
-
|
35
|
-
#Tasks gleaned from merb-core's Rakefile
|
36
|
-
|
37
|
-
desc "Run :gem and install the resulting .gem"
|
38
|
-
task :install => :gem do
|
39
|
-
cmd = "#{SUDO} gem install #{install_home} --local pkg/#{NAME}-#{GitRemoteBranch::VERSION}.gem --no-rdoc --no-ri"
|
40
|
-
puts cmd
|
41
|
-
`#{cmd}`
|
42
|
-
end
|
43
|
-
|
44
|
-
desc "Uninstall the .gem"
|
45
|
-
task :uninstall do
|
46
|
-
cmd = "#{SUDO} gem uninstall #{NAME} -x"
|
47
|
-
#TODO fix this crap
|
48
|
-
puts cmd, ' (Note: execute manually if more than one version is installed)'
|
49
|
-
`#{cmd}`
|
50
|
-
end
|
51
|
-
end
|
data/TODO
CHANGED
@@ -1,16 +1,7 @@
|
|
1
1
|
- tests :-)
|
2
|
-
-
|
3
|
-
-
|
4
|
-
-
|
5
|
-
- New functionality:
|
6
|
-
- Remotize an existing local branch (aliases: publish share make_remote makeremote)
|
7
|
-
git push origin branch_name:refs/heads/branch_name
|
8
|
-
git fetch origin
|
9
|
-
(find a local branch other than the branch to remotize)
|
10
|
-
git checkout master
|
11
|
-
git branch --track -f branch_name origin/branch_name
|
12
|
-
(yay! we don't have to delete the local one...)
|
13
|
-
- add support for different remote name (--remote-name)
|
2
|
+
- offer help when branch -d fails
|
3
|
+
- connect (new remote repo)
|
4
|
+
- Make remotize work when not specifying the local branch (and use this one by default)
|
14
5
|
- avoid deleting local branches when tracking with the help of git-config ?
|
15
6
|
|
16
7
|
- drop assumption that master can be treated differently than other branches (e.g. considered as a safe checkout)
|
@@ -18,3 +9,8 @@
|
|
18
9
|
- is it even necessary to be on a branch per se? I think not...
|
19
10
|
- survive checkouts with wrong case
|
20
11
|
e.g.: branch "Bob" checked out branch 'bob'. git branch -l won't correctly flag branch Bob as current.
|
12
|
+
|
13
|
+
- better exit status behavior
|
14
|
+
- Add verification if remote delete didn't work
|
15
|
+
- add support for different remote name (--remote-name)
|
16
|
+
|
data/bin/grb
CHANGED
@@ -7,12 +7,19 @@ require "#{File.dirname(THIS_FILE)}/../lib/git_remote_branch"
|
|
7
7
|
|
8
8
|
include GitRemoteBranch
|
9
9
|
|
10
|
-
|
10
|
+
begin
|
11
|
+
p = read_params(ARGV)
|
12
|
+
rescue InvalidBranchError => ex
|
13
|
+
puts ex.message
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
$SILENT = p[:silent]
|
11
18
|
|
12
|
-
|
19
|
+
whisper get_welcome
|
13
20
|
|
14
21
|
if p[:action] == :help
|
15
|
-
|
22
|
+
whisper get_usage
|
16
23
|
exit 0
|
17
24
|
end
|
18
25
|
|
data/lib/git_remote_branch.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
|
-
grb_app_root = File.expand_path( File.dirname(__FILE__) + '/..' )
|
2
|
-
|
3
1
|
require 'rubygems'
|
4
2
|
require 'colored'
|
5
3
|
|
4
|
+
grb_app_root = File.expand_path( File.dirname(__FILE__) + '/..' )
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift( grb_app_root + '/vendor' )
|
7
|
+
require 'capture_fu'
|
8
|
+
|
6
9
|
$LOAD_PATH.unshift( grb_app_root + '/lib' )
|
7
10
|
require 'param_reader'
|
11
|
+
require 'version'
|
8
12
|
|
9
13
|
module GitRemoteBranch
|
10
|
-
|
14
|
+
class InvalidBranchError < RuntimeError; end
|
15
|
+
class NotOnGitRepositoryError < RuntimeError; end
|
11
16
|
|
12
17
|
COMMANDS = {
|
13
18
|
:create => {
|
@@ -21,9 +26,21 @@ module GitRemoteBranch
|
|
21
26
|
]
|
22
27
|
},
|
23
28
|
|
29
|
+
:publish => {
|
30
|
+
:description => 'publish an exiting local branch',
|
31
|
+
:aliases => %w{publish remotize},
|
32
|
+
:commands => [
|
33
|
+
'"git push #{origin} #{branch_name}:refs/heads/#{branch_name}"',
|
34
|
+
'"git fetch #{origin}"',
|
35
|
+
'"git config branch.#{branch_name}.remote #{origin}"',
|
36
|
+
'"git config branch.#{branch_name}.merge refs/heads/#{branch_name}"',
|
37
|
+
'"git checkout #{branch_name}"'
|
38
|
+
]
|
39
|
+
},
|
40
|
+
|
24
41
|
:rename => {
|
25
42
|
:description => 'rename a remote branch and its local tracking branch',
|
26
|
-
:aliases => %w{ rn mv move
|
43
|
+
:aliases => %w{rename rn mv move},
|
27
44
|
:commands => [
|
28
45
|
'"git push #{origin} #{current_branch}:refs/heads/#{branch_name}"',
|
29
46
|
'"git fetch #{origin}"',
|
@@ -53,25 +70,39 @@ module GitRemoteBranch
|
|
53
70
|
'"git branch --track #{branch_name} #{origin}/#{branch_name}"'
|
54
71
|
]
|
55
72
|
}
|
56
|
-
}
|
57
|
-
|
58
|
-
def
|
59
|
-
|
73
|
+
} unless defined?(COMMANDS)
|
74
|
+
|
75
|
+
def self.get_reverse_map(commands)
|
76
|
+
h={}
|
77
|
+
commands.each_pair do |cmd, params|
|
78
|
+
params[:aliases].each do |alias_|
|
79
|
+
unless h[alias_]
|
80
|
+
h[alias_] = cmd
|
81
|
+
else
|
82
|
+
raise "Duplicate aliases: #{alias_.inspect} already defined for command #{h[alias_].inspect}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
h
|
87
|
+
end
|
88
|
+
ALIAS_REVERSE_MAP = get_reverse_map(COMMANDS) unless defined?(ALIAS_REVERSE_MAP)
|
89
|
+
|
90
|
+
def get_welcome
|
91
|
+
"git_remote_branch version #{VERSION::STRING}\n\n"
|
60
92
|
end
|
61
93
|
|
62
|
-
def
|
63
|
-
|
94
|
+
def get_usage
|
95
|
+
return <<-HELP
|
64
96
|
Usage:
|
65
97
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
If origin_server is not specified, the name 'origin' is assumed (git's default)
|
98
|
+
#{[:create, :publish, :rename, :delete, :track].map{|action|
|
99
|
+
" grb #{action} branch_name [origin_server] \n\n"
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
Notes:
|
104
|
+
- If origin_server is not specified, the name 'origin' is assumed (git's default)
|
105
|
+
- The rename functionality renames the current branch
|
75
106
|
|
76
107
|
The explain meta-command: you can also prepend any command with the keyword 'explain'. Instead of executing the command, git_remote_branch will simply output the list of commands you need to run to accomplish that goal.
|
77
108
|
Example:
|
@@ -92,22 +123,29 @@ module GitRemoteBranch
|
|
92
123
|
def explain_action(action, branch_name, origin, current_branch)
|
93
124
|
cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact
|
94
125
|
|
95
|
-
|
126
|
+
whisper "List of operations to do to #{COMMANDS[action][:description]}:", ''
|
96
127
|
puts_cmd cmds
|
97
|
-
|
128
|
+
whisper ''
|
98
129
|
end
|
99
130
|
|
100
131
|
def execute_cmds(*cmds)
|
132
|
+
silencer = $SILENT ? ' 2>&1' : ''
|
101
133
|
cmds.flatten.each do |c|
|
102
134
|
puts_cmd c
|
103
|
-
`#{c}`
|
104
|
-
|
135
|
+
`#{c}#{silencer}`
|
136
|
+
whisper ''
|
105
137
|
end
|
106
138
|
end
|
107
139
|
|
108
140
|
def puts_cmd(*cmds)
|
109
141
|
cmds.flatten.each do |c|
|
110
|
-
|
142
|
+
whisper "#{c}".red
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def whisper(*msgs)
|
147
|
+
unless $SILENT
|
148
|
+
msgs.flatten ? msgs.flatten.each{|m| puts m} : puts
|
111
149
|
end
|
112
150
|
end
|
113
151
|
end
|
data/lib/param_reader.rb
CHANGED
@@ -1,18 +1,40 @@
|
|
1
1
|
module GitRemoteBranch
|
2
|
+
include ::CaptureFu
|
3
|
+
|
4
|
+
private
|
5
|
+
HELP_PARAMS = {:action => :help}
|
6
|
+
|
7
|
+
public
|
2
8
|
def read_params(argv)
|
9
|
+
#TODO Some validation on the params
|
10
|
+
|
3
11
|
p={}
|
4
|
-
p[:
|
5
|
-
p[:
|
6
|
-
|
7
|
-
p[:
|
8
|
-
p[:current_branch] = get_current_branch
|
12
|
+
p[:silent] = silent!(argv)
|
13
|
+
p[:explain] = explain_mode!(argv)
|
14
|
+
|
15
|
+
p[:action] = get_action(argv[0]) or return HELP_PARAMS
|
9
16
|
|
10
|
-
|
11
|
-
p[:branch] ||= "branch_to_#{p[:action]}" if p[:explain]
|
17
|
+
return HELP_PARAMS if p[:action] == :help
|
12
18
|
|
13
|
-
|
19
|
+
p[:branch] = get_branch(argv[1])
|
20
|
+
p[:origin] = get_origin(argv[2])
|
21
|
+
|
22
|
+
# If in explain mode, the user doesn't have to specify a branch or be on in
|
23
|
+
# actual repo to get the explanation.
|
24
|
+
# Of course if he is, the explanation will be made better by using contextual info.
|
25
|
+
if p[:explain]
|
26
|
+
p[:branch] ||= "branch_to_#{p[:action]}"
|
27
|
+
p[:current_branch] = begin
|
28
|
+
get_current_branch
|
29
|
+
rescue NotOnGitRepositoryError, InvalidBranchError
|
30
|
+
'current_branch'
|
31
|
+
end
|
14
32
|
|
15
|
-
|
33
|
+
else
|
34
|
+
return HELP_PARAMS unless p[:branch]
|
35
|
+
p[:current_branch] = get_current_branch
|
36
|
+
end
|
37
|
+
return p
|
16
38
|
end
|
17
39
|
|
18
40
|
def explain_mode!(argv)
|
@@ -23,14 +45,13 @@ module GitRemoteBranch
|
|
23
45
|
false
|
24
46
|
end
|
25
47
|
end
|
48
|
+
|
49
|
+
def silent!(argv)
|
50
|
+
!!argv.delete('--silent')
|
51
|
+
end
|
26
52
|
|
27
53
|
def get_action(action)
|
28
|
-
|
29
|
-
return :create if COMMANDS[:create][:aliases].include?(a)
|
30
|
-
return :delete if COMMANDS[:delete][:aliases].include?(a)
|
31
|
-
return :track if COMMANDS[:track][:aliases].include?(a)
|
32
|
-
return :rename if COMMANDS[:rename][:aliases].include?(a)
|
33
|
-
return nil
|
54
|
+
ALIAS_REVERSE_MAP[action.to_s.downcase]
|
34
55
|
end
|
35
56
|
|
36
57
|
def get_branch(branch)
|
@@ -41,12 +62,23 @@ module GitRemoteBranch
|
|
41
62
|
return origin || 'origin'
|
42
63
|
end
|
43
64
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
65
|
+
private
|
66
|
+
BRANCH_LISTING_COMMAND = 'git branch -l'.freeze
|
67
|
+
|
68
|
+
public
|
69
|
+
def get_current_branch
|
70
|
+
#This is sensitive to checkouts of branches specified with wrong case
|
71
|
+
|
72
|
+
listing = capture_process_output("#{BRANCH_LISTING_COMMAND}")[1]
|
73
|
+
raise(NotOnGitRepositoryError, listing.chomp) if listing =~ /Not a git repository/i
|
74
|
+
|
75
|
+
current_branch = listing.scan(/^\*\s+(.+)/).flatten.first
|
76
|
+
|
77
|
+
if current_branch =~ /\(no branch\)/
|
78
|
+
raise InvalidBranchError, ["Couldn't identify the current local branch. The branch listing was:",
|
79
|
+
BRANCH_LISTING_COMMAND.red,
|
80
|
+
listing].join("\n")
|
81
|
+
end
|
82
|
+
current_branch.strip
|
49
83
|
end
|
50
|
-
raise "Couldn't identify the current local branch."
|
51
|
-
end
|
52
84
|
end
|