webmat-git_remote_branch 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +27 -19
- data/Rakefile +4 -1
- data/TODO +8 -32
- data/bin/grb +8 -19
- data/lib/git_remote_branch.rb +66 -81
- data/lib/param_reader.rb +51 -0
- data/test/git_helper.rb +1 -1
- metadata +12 -5
- data/vendor/capture_fu/capture_fu.rb +0 -60
- data/vendor/try_require/try_require.rb +0 -18
data/README
CHANGED
@@ -1,48 +1,56 @@
|
|
1
|
-
Why git_remote_branch?
|
1
|
+
==== Why git_remote_branch? ====
|
2
2
|
|
3
3
|
The basic idea for git_remote_branch is to trivialize the interaction with
|
4
|
-
remote branches in simple situations.
|
5
|
-
|
6
|
-
|
4
|
+
remote branches in simple situations.
|
5
|
+
|
6
|
+
For now git_remote_branch assumes that the local and remote branches have the
|
7
|
+
same name. Multiple origins are supported.
|
7
8
|
|
8
9
|
Another goal of git_remote_branch is to help teach the real underlying git
|
9
10
|
commands. Each operation done on your behalf is displayed at the console.
|
10
11
|
|
11
12
|
|
12
13
|
|
13
|
-
Installation
|
14
|
+
==== Installation ====
|
15
|
+
|
16
|
+
sudo gem install webmat-git_remote_branch --source=http://gems.github.com
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
Note: don't add gems.github.com as a permanent source for your gems. Check out
|
19
|
+
http://gems.github.com for more information on the matter. If you've included
|
20
|
+
it already and find yourself in trouble, check out
|
21
|
+
http://chalain.livejournal.com/71260.html.
|
17
22
|
|
18
23
|
|
19
24
|
|
20
|
-
Usage
|
25
|
+
==== Usage ====
|
21
26
|
|
22
27
|
Notes:
|
23
28
|
- parts between brackets are optional
|
24
29
|
- When 'origin_server' is not specified, the name 'origin' is assumed.
|
25
30
|
|
26
|
-
$ grb [-h] #=> Displays help
|
27
|
-
|
28
31
|
Available commands (with aliases):
|
29
32
|
|
30
|
-
|
31
|
-
|
33
|
+
== Help ==
|
34
|
+
|
35
|
+
$ grb [-h] #=> Displays help
|
36
|
+
|
37
|
+
== create (alias: new) ==
|
38
|
+
Create a new local branch as well as a corresponding remote branch from the
|
39
|
+
branch you are currently on.
|
32
40
|
Automatically track the new remote branch (useful for pulling and merging).
|
33
41
|
Switch to the new branch.
|
34
42
|
|
35
43
|
$ grb create branch_name [origin_server]
|
36
44
|
|
37
45
|
|
38
|
-
delete (aliases: destroy, kill)
|
46
|
+
== delete (aliases: destroy, kill) ==
|
39
47
|
Delete the remote branch then delete the local branch.
|
40
48
|
The local branch is not deleted if there are pending changes.
|
41
49
|
|
42
50
|
$ grb delete branch_name [origin_server]
|
43
51
|
|
44
52
|
|
45
|
-
track (aliases: follow grab)
|
53
|
+
== track (aliases: follow grab) ==
|
46
54
|
Track an existing remote branch locally.
|
47
55
|
|
48
56
|
|
@@ -50,7 +58,7 @@ $ grb track branch_name [origin_server]
|
|
50
58
|
|
51
59
|
|
52
60
|
|
53
|
-
History
|
61
|
+
==== History ====
|
54
62
|
|
55
63
|
This script was originally created by Carl Mercier and made public on his blog
|
56
64
|
here:
|
@@ -58,12 +66,12 @@ here:
|
|
58
66
|
No nonsense GIT, part 1: git-remote-branch
|
59
67
|
http://blog.carlmercier.com/2008/01/25/no-nonsense-git-part-1-git-remote-branch/
|
60
68
|
|
61
|
-
|
62
|
-
|
63
|
-
|
69
|
+
|
70
|
+
I'm using it as a starting point to make it even easier to interact with remote
|
71
|
+
repositories.
|
64
72
|
|
65
73
|
|
74
|
+
=== Contributors ===
|
66
75
|
|
67
|
-
Contributors
|
68
76
|
- Mathieu Martin webmat@gmail.com
|
69
77
|
- Carl Mercier (Carl: want your email here?)
|
data/Rakefile
CHANGED
@@ -43,6 +43,9 @@ namespace :gem do
|
|
43
43
|
|
44
44
|
desc "Uninstall the .gem"
|
45
45
|
task :uninstall do
|
46
|
-
|
46
|
+
cmd = "#{SUDO} gem uninstall #{NAME}"
|
47
|
+
#TODO fix this crap
|
48
|
+
puts cmd, ' (Note: execute manually if more than one version is installed)'
|
49
|
+
`#{cmd}`
|
47
50
|
end
|
48
51
|
end
|
data/TODO
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
- Put in evidence the tutorial part of each grb action
|
2
|
-
- colorize the git commands
|
3
|
-
- Add 'explain' / 'show' command
|
4
1
|
- tests :-)
|
5
|
-
- re-architect the code a bit?
|
6
2
|
- better exit status behavior
|
7
3
|
- Add verification if remote delete didn't work
|
8
4
|
- New functionality:
|
@@ -13,31 +9,11 @@
|
|
13
9
|
git checkout master
|
14
10
|
git branch --track -f branch_name origin/branch_name
|
15
11
|
(yay! we don't have to delete the local one...)
|
16
|
-
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
Executing: git branch --track aaron origin/aaron
|
25
|
-
fatal: Not a valid object name: 'origin/aaron'.
|
26
|
-
|
27
|
-
|
28
|
-
mathieu@ml code (master)$ git fetch
|
29
|
-
remote: Counting objects: 87, done.
|
30
|
-
remote: Compressing objects: 100% (45/45), done.
|
31
|
-
remote: Total 51 (delta 13), reused 40 (delta 5)
|
32
|
-
Unpacking objects: 100% (51/51), done.
|
33
|
-
From git@github.com:webmat/priv_repo
|
34
|
-
* [new branch] aaron -> origin/aaron
|
35
|
-
|
36
|
-
mathieu@ml code (master)$ grbd follow aaron
|
37
|
-
git_remote_branch version 0.2.1
|
38
|
-
----------------------------------------------------------------------
|
39
|
-
|
40
|
-
Executing: git branch --track aaron origin/aaron
|
41
|
-
|
42
|
-
|
43
|
-
|
12
|
+
- add support for different remote name (--remote-name)
|
13
|
+
- avoid deleting local branches when tracking with the help of git-config ?
|
14
|
+
|
15
|
+
- drop assumption that master can be treated differently than other branches (e.g. considered as a safe checkout)
|
16
|
+
- reliance on current_branch
|
17
|
+
- is it even necessary to be on a branch per se? I think not...
|
18
|
+
- survive checkouts with wrong case
|
19
|
+
e.g.: branch "Bob" checked out branch 'bob'. git branch -l won't correctly flag branch Bob as current.
|
data/bin/grb
CHANGED
@@ -1,33 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# Check out the README (or try grb
|
3
|
+
# Check out the README (or try 'grb help') before you screw up your repos ;-)
|
4
|
+
|
5
|
+
require "#{File.dirname(__FILE__)}/../lib/git_remote_branch"
|
4
6
|
|
5
|
-
require File.expand_path( File.join( [File.dirname(__FILE__)] + %w{ .. lib git_remote_branch } ) )
|
6
7
|
include GitRemoteBranch
|
7
8
|
|
8
9
|
print_welcome
|
9
10
|
|
10
|
-
p = read_params
|
11
|
+
p = read_params(ARGV)
|
11
12
|
|
12
13
|
if p[:action] == :help
|
13
14
|
print_usage
|
14
15
|
exit 0
|
15
16
|
end
|
16
17
|
|
17
|
-
if p[:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
case p[:action]
|
24
|
-
when :create
|
25
|
-
create_branch(p[:branch], p[:origin], p[:current_branch])
|
26
|
-
when :delete
|
27
|
-
delete_branch(p[:branch], p[:origin], p[:current_branch])
|
28
|
-
when :track
|
29
|
-
track_branch(p[:branch], p[:origin])
|
30
|
-
else
|
31
|
-
print_usage
|
32
|
-
exit 1
|
18
|
+
if p[:explain]
|
19
|
+
explain_action(p[:action], p[:branch], p[:origin], p[:current_branch])
|
20
|
+
else
|
21
|
+
execute_action(p[:action], p[:branch], p[:origin], p[:current_branch])
|
33
22
|
end
|
data/lib/git_remote_branch.rb
CHANGED
@@ -1,108 +1,93 @@
|
|
1
|
+
grb_app_root = File.expand_path( File.dirname(__FILE__) + '/..' )
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'colored'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift( grb_app_root + '/lib' )
|
7
|
+
require 'param_reader'
|
8
|
+
|
1
9
|
module GitRemoteBranch
|
2
|
-
VERSION = '0.2.
|
10
|
+
VERSION = '0.2.2'
|
11
|
+
|
12
|
+
COMMANDS = {
|
13
|
+
:create => {
|
14
|
+
:description => 'create a new remote branch and track it locally',
|
15
|
+
:aliases => %w{create new},
|
16
|
+
:commands => [
|
17
|
+
'"git push #{origin} #{current_branch}:refs/heads/#{branch_name}"',
|
18
|
+
'"git fetch #{origin}"',
|
19
|
+
'"git branch --track #{branch_name} #{origin}/#{branch_name}"',
|
20
|
+
'"git checkout #{branch_name}"'
|
21
|
+
]
|
22
|
+
},
|
3
23
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
24
|
+
:delete => {
|
25
|
+
:description => 'delete a local and a remote branch',
|
26
|
+
:aliases => %w{delete destroy kill remove},
|
27
|
+
:commands => [
|
28
|
+
'"git push #{origin} :refs/heads/#{branch_name}"',
|
29
|
+
'"git checkout master" if current_branch == branch_name',
|
30
|
+
'"git branch -d #{branch_name}"'
|
31
|
+
]
|
32
|
+
},
|
33
|
+
|
34
|
+
:track => {
|
35
|
+
:description => 'track an existing remote branch',
|
36
|
+
:aliases => %w{track follow grab fetch},
|
37
|
+
:commands => [
|
38
|
+
'"git fetch #{origin}"',
|
39
|
+
'"git checkout master" if current_branch == branch_name',
|
40
|
+
'"git branch --track #{branch_name} #{origin}/#{branch_name}"'
|
41
|
+
]
|
42
|
+
}
|
8
43
|
}
|
9
44
|
|
10
45
|
def print_welcome
|
11
|
-
puts "git_remote_branch version #{VERSION}", '
|
46
|
+
puts "git_remote_branch version #{VERSION}", ''
|
12
47
|
end
|
13
48
|
|
14
49
|
def print_usage
|
15
50
|
puts <<-HELP
|
16
51
|
Usage:
|
17
52
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
If origin_server is not specified, the name 'origin' is assumed
|
53
|
+
grb create branch_name [origin_server]
|
54
|
+
|
55
|
+
grb delete branch_name [origin_server]
|
56
|
+
|
57
|
+
grb track branch_name [origin_server]
|
58
|
+
|
59
|
+
If origin_server is not specified, the name 'origin' is assumed (git's default)
|
25
60
|
|
26
61
|
All commands also have aliases:
|
27
|
-
#{
|
28
|
-
"#{
|
62
|
+
#{ COMMANDS.keys.map{|k| k.to_s}.sort.map {|cmd|
|
63
|
+
"#{cmd}: #{COMMANDS[cmd.to_sym][:aliases].join(', ')}" }.join("\n ") }
|
29
64
|
HELP
|
30
65
|
end
|
31
66
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
return res, out, err
|
67
|
+
def execute_action(action, branch_name, origin, current_branch)
|
68
|
+
cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact
|
69
|
+
execute_cmds(cmds)
|
37
70
|
end
|
38
71
|
|
39
|
-
def
|
40
|
-
cmds.
|
41
|
-
puts "Executing: #{c}"
|
42
|
-
`#{c}`
|
43
|
-
puts ""
|
44
|
-
end
|
45
|
-
end
|
72
|
+
def explain_action(action, branch_name, origin, current_branch)
|
73
|
+
cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact
|
46
74
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
cmd << "git fetch #{origin}"
|
51
|
-
cmd << "git branch --track #{branch_name} #{origin}/#{branch_name}"
|
52
|
-
cmd << "git checkout #{branch_name}"
|
53
|
-
execute_cmds(cmd)
|
75
|
+
puts "List of operations to do to #{COMMANDS[action][:description]}:", ''
|
76
|
+
puts_cmd cmds
|
77
|
+
puts ''
|
54
78
|
end
|
55
79
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
execute_cmds(cmd)
|
62
|
-
end
|
63
|
-
|
64
|
-
def track_branch(branch_name, origin)
|
65
|
-
cmd = ["git branch --track #{branch_name} #{origin}/#{branch_name}"]
|
66
|
-
execute_cmds(cmd)
|
67
|
-
end
|
68
|
-
|
69
|
-
def get_current_branch
|
70
|
-
x = `git branch -l`
|
71
|
-
x.each_line do |l|
|
72
|
-
return l.sub("*","").strip if l[0] == 42
|
80
|
+
def execute_cmds(*cmds)
|
81
|
+
cmds.flatten.each do |c|
|
82
|
+
puts_cmd c
|
83
|
+
`#{c}`
|
84
|
+
puts ''
|
73
85
|
end
|
74
|
-
|
75
|
-
puts "Couldn't identify the current local branch."
|
76
|
-
return nil
|
77
86
|
end
|
78
87
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
return :delete if CMD_ALIASES[:delete].include?(a)
|
83
|
-
return :track if CMD_ALIASES[:track].include?(a)
|
84
|
-
return nil
|
85
|
-
end
|
86
|
-
|
87
|
-
def get_branch
|
88
|
-
ARGV[1].downcase
|
89
|
-
end
|
90
|
-
|
91
|
-
def get_origin
|
92
|
-
return ARGV[2] if ARGV.size > 2
|
93
|
-
return "origin"
|
94
|
-
end
|
95
|
-
|
96
|
-
def read_params
|
97
|
-
p={}
|
98
|
-
begin
|
99
|
-
p[:action] = get_action
|
100
|
-
p[:branch] = get_branch
|
101
|
-
p[:origin] = get_origin
|
102
|
-
p[:current_branch] = get_current_branch
|
103
|
-
p
|
104
|
-
rescue
|
105
|
-
{:action=>:help}
|
88
|
+
def puts_cmd(*cmds)
|
89
|
+
cmds.flatten.each do |c|
|
90
|
+
puts "#{c}".red
|
106
91
|
end
|
107
92
|
end
|
108
93
|
end
|
data/lib/param_reader.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module GitRemoteBranch
|
2
|
+
def read_params(argv)
|
3
|
+
p={}
|
4
|
+
p[:explain] = explain_mode!(argv)
|
5
|
+
p[:action] = get_action(argv[0]) || :help
|
6
|
+
p[:branch] = get_branch(argv[1])
|
7
|
+
p[:origin] = get_origin(argv[2])
|
8
|
+
p[:current_branch] = get_current_branch
|
9
|
+
|
10
|
+
#If in explain mode, the user doesn't have to specify a branch to get the explanation
|
11
|
+
p[:branch] ||= "branch_to_#{p[:action]}" if p[:explain]
|
12
|
+
|
13
|
+
#TODO Some validation on the params
|
14
|
+
|
15
|
+
p
|
16
|
+
end
|
17
|
+
|
18
|
+
def explain_mode!(argv)
|
19
|
+
if argv[0].to_s.downcase == 'explain'
|
20
|
+
argv.shift
|
21
|
+
true
|
22
|
+
else
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_action(action)
|
28
|
+
a = action.to_s.downcase
|
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 nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_branch(branch)
|
36
|
+
branch
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_origin(origin)
|
40
|
+
return origin || 'origin'
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_current_branch
|
44
|
+
#This is sensitive to checkouts of branches specified with wrong case
|
45
|
+
x = `git branch -l`
|
46
|
+
x.each_line do |l|
|
47
|
+
return l.sub("*","").strip if l =~ /\A\*/ and not l =~ /\(no branch\)/
|
48
|
+
end
|
49
|
+
raise "Couldn't identify the current local branch."
|
50
|
+
end
|
51
|
+
end
|
data/test/git_helper.rb
CHANGED
@@ -4,7 +4,7 @@ require 'tmpdir'
|
|
4
4
|
# Instantiating a GitHelper object creates a temp directory containing 3 repos.
|
5
5
|
# 1 that's considered the remote repo and 2 peer local repos (local1 and local2).
|
6
6
|
# All 3 are synchronized with the same data (they contain a few dummy files).
|
7
|
-
# Once instantiated you can access the 3 full repo locations
|
7
|
+
# Once instantiated you can access the 3 full repo locations through attribute readers
|
8
8
|
# remote, local1 and local2.
|
9
9
|
class GitHelper
|
10
10
|
include FileUtils
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webmat-git_remote_branch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mathieu Martin
|
@@ -12,8 +12,16 @@ cert_chain: []
|
|
12
12
|
|
13
13
|
date: 2008-06-13 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: colored
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.1"
|
24
|
+
version:
|
17
25
|
description: git_remote_branch is a learning tool to ease the interaction with remote branches in simple situations.
|
18
26
|
email: webmat@gmail.com
|
19
27
|
executables:
|
@@ -28,8 +36,7 @@ files:
|
|
28
36
|
- TODO
|
29
37
|
- bin/grb
|
30
38
|
- lib/git_remote_branch.rb
|
31
|
-
-
|
32
|
-
- vendor/capture_fu/capture_fu.rb
|
39
|
+
- lib/param_reader.rb
|
33
40
|
- test/git_helper.rb
|
34
41
|
- test/test_helper.rb
|
35
42
|
- test/unit/git_helper_test.rb
|
@@ -1,60 +0,0 @@
|
|
1
|
-
# This is a very early version of capture_fu.
|
2
|
-
# See github.com/webmat/capture_fu for more info.
|
3
|
-
module CaptureFu
|
4
|
-
VERSION = '0.0.1'
|
5
|
-
|
6
|
-
def capture_output(&block)
|
7
|
-
real_out, real_err = $stdout, $stderr
|
8
|
-
result = fake_out = fake_err = nil
|
9
|
-
begin
|
10
|
-
fake_out, fake_err = Helpers::PipeStealer.new, Helpers::PipeStealer.new
|
11
|
-
$stdout, $stderr = fake_out, fake_err
|
12
|
-
result = yield
|
13
|
-
ensure
|
14
|
-
$stdout, $stderr = real_out, real_err
|
15
|
-
end
|
16
|
-
return result, fake_out.captured, fake_err.captured
|
17
|
-
end
|
18
|
-
|
19
|
-
# This first implementation is only intended for batch executions.
|
20
|
-
# You can't pipe stuff programmatically to the child process.
|
21
|
-
def capture_process_output(command)
|
22
|
-
|
23
|
-
#capture stderr in the same stream
|
24
|
-
command << ' 2>&1' unless Helpers.stderr_already_redirected(command)
|
25
|
-
|
26
|
-
out = `#{command}`
|
27
|
-
return $?.exitstatus, out
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
module Helpers
|
34
|
-
|
35
|
-
def self.stderr_already_redirected(command)
|
36
|
-
#Already redirected to stdout (valid for Windows)
|
37
|
-
return true if command =~ /2>&1\s*\Z/
|
38
|
-
|
39
|
-
#Redirected to /dev/null (this is clearly POSIX-dependent)
|
40
|
-
return true if command =~ /2>\/dev\/null\s*\Z/
|
41
|
-
|
42
|
-
return false
|
43
|
-
end
|
44
|
-
|
45
|
-
class PipeStealer < File
|
46
|
-
attr_reader :captured
|
47
|
-
def initialize
|
48
|
-
@captured = ''
|
49
|
-
end
|
50
|
-
def write(s)
|
51
|
-
@captured << s
|
52
|
-
end
|
53
|
-
def captured
|
54
|
-
return nil if @captured.empty?
|
55
|
-
@captured.dup
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
end #Helper module
|
60
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# This is a very early version of try_require.
|
2
|
-
# See github.com/webmat/try_require for more info.
|
3
|
-
def try_require(what, &block)
|
4
|
-
loaded, require_result = false, nil
|
5
|
-
|
6
|
-
begin
|
7
|
-
require_result = require what
|
8
|
-
loaded = true
|
9
|
-
|
10
|
-
rescue LoadError => ex
|
11
|
-
puts "Unable to require '#{what}'", "#{ex.class}: #{ex.message}"
|
12
|
-
end
|
13
|
-
|
14
|
-
yield if loaded and block_given?
|
15
|
-
|
16
|
-
require_result
|
17
|
-
end
|
18
|
-
|