git_remote_branch 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +77 -0
- data/Rakefile +51 -0
- data/TODO +20 -0
- data/bin/grb +22 -0
- data/lib/git_remote_branch.rb +93 -0
- data/lib/param_reader.rb +51 -0
- data/test/git_helper.rb +57 -0
- data/test/test_helper.rb +27 -0
- data/test/unit/git_helper_test.rb +30 -0
- metadata +73 -0
data/README
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
==== Why git_remote_branch? ====
|
2
|
+
|
3
|
+
The basic idea for git_remote_branch is to trivialize the interaction with
|
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.
|
8
|
+
|
9
|
+
Another goal of git_remote_branch is to help teach the real underlying git
|
10
|
+
commands. Each operation done on your behalf is displayed at the console.
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
==== Installation ====
|
15
|
+
|
16
|
+
sudo gem install webmat-git_remote_branch --source=http://gems.github.com
|
17
|
+
|
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.
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
==== Usage ====
|
26
|
+
|
27
|
+
Notes:
|
28
|
+
- parts between brackets are optional
|
29
|
+
- When 'origin_server' is not specified, the name 'origin' is assumed.
|
30
|
+
|
31
|
+
Available commands (with aliases):
|
32
|
+
|
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.
|
40
|
+
Automatically track the new remote branch (useful for pulling and merging).
|
41
|
+
Switch to the new branch.
|
42
|
+
|
43
|
+
$ grb create branch_name [origin_server]
|
44
|
+
|
45
|
+
|
46
|
+
== delete (aliases: destroy, kill) ==
|
47
|
+
Delete the remote branch then delete the local branch.
|
48
|
+
The local branch is not deleted if there are pending changes.
|
49
|
+
|
50
|
+
$ grb delete branch_name [origin_server]
|
51
|
+
|
52
|
+
|
53
|
+
== track (aliases: follow grab) ==
|
54
|
+
Track an existing remote branch locally.
|
55
|
+
|
56
|
+
|
57
|
+
$ grb track branch_name [origin_server]
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
==== History ====
|
62
|
+
|
63
|
+
This script was originally created by Carl Mercier and made public on his blog
|
64
|
+
here:
|
65
|
+
|
66
|
+
No nonsense GIT, part 1: git-remote-branch
|
67
|
+
http://blog.carlmercier.com/2008/01/25/no-nonsense-git-part-1-git-remote-branch/
|
68
|
+
|
69
|
+
|
70
|
+
I'm using it as a starting point to make it even easier to interact with remote
|
71
|
+
repositories.
|
72
|
+
|
73
|
+
|
74
|
+
=== Contributors ===
|
75
|
+
|
76
|
+
- Mathieu Martin webmat@gmail.com
|
77
|
+
- Carl Mercier (Carl: want your email here?)
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
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
|
+
windows = (RUBY_PLATFORM =~ /win32|cygwin/) rescue nil
|
15
|
+
install_home = ENV['GEM_HOME'] ? "-i #{ENV['GEM_HOME']}" : ""
|
16
|
+
SUDO = windows ? "" : "sudo"
|
17
|
+
|
18
|
+
|
19
|
+
Rake::TestTask.new(:test) do |t|
|
20
|
+
t.pattern = 'test/**/*_test.rb'
|
21
|
+
t.verbose = true
|
22
|
+
end
|
23
|
+
|
24
|
+
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}"
|
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
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
- tests :-)
|
2
|
+
- displaying help shouldn't need grb to execute in a git working dir...
|
3
|
+
- better exit status behavior
|
4
|
+
- Add verification if remote delete didn't work
|
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)
|
14
|
+
- avoid deleting local branches when tracking with the help of git-config ?
|
15
|
+
|
16
|
+
- drop assumption that master can be treated differently than other branches (e.g. considered as a safe checkout)
|
17
|
+
- reliance on current_branch
|
18
|
+
- is it even necessary to be on a branch per se? I think not...
|
19
|
+
- survive checkouts with wrong case
|
20
|
+
e.g.: branch "Bob" checked out branch 'bob'. git branch -l won't correctly flag branch Bob as current.
|
data/bin/grb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
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"
|
6
|
+
|
7
|
+
include GitRemoteBranch
|
8
|
+
|
9
|
+
print_welcome
|
10
|
+
|
11
|
+
p = read_params(ARGV)
|
12
|
+
|
13
|
+
if p[:action] == :help
|
14
|
+
print_usage
|
15
|
+
exit 0
|
16
|
+
end
|
17
|
+
|
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])
|
22
|
+
end
|
@@ -0,0 +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
|
+
|
9
|
+
module GitRemoteBranch
|
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
|
+
},
|
23
|
+
|
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
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
def print_welcome
|
46
|
+
puts "git_remote_branch version #{VERSION}", ''
|
47
|
+
end
|
48
|
+
|
49
|
+
def print_usage
|
50
|
+
puts <<-HELP
|
51
|
+
Usage:
|
52
|
+
|
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)
|
60
|
+
|
61
|
+
All commands also have aliases:
|
62
|
+
#{ COMMANDS.keys.map{|k| k.to_s}.sort.map {|cmd|
|
63
|
+
"#{cmd}: #{COMMANDS[cmd.to_sym][:aliases].join(', ')}" }.join("\n ") }
|
64
|
+
HELP
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute_action(action, branch_name, origin, current_branch)
|
68
|
+
cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact
|
69
|
+
execute_cmds(cmds)
|
70
|
+
end
|
71
|
+
|
72
|
+
def explain_action(action, branch_name, origin, current_branch)
|
73
|
+
cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact
|
74
|
+
|
75
|
+
puts "List of operations to do to #{COMMANDS[action][:description]}:", ''
|
76
|
+
puts_cmd cmds
|
77
|
+
puts ''
|
78
|
+
end
|
79
|
+
|
80
|
+
def execute_cmds(*cmds)
|
81
|
+
cmds.flatten.each do |c|
|
82
|
+
puts_cmd c
|
83
|
+
`#{c}`
|
84
|
+
puts ''
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def puts_cmd(*cmds)
|
89
|
+
cmds.flatten.each do |c|
|
90
|
+
puts "#{c}".red
|
91
|
+
end
|
92
|
+
end
|
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
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
# Instantiating a GitHelper object creates a temp directory containing 3 repos.
|
5
|
+
# 1 that's considered the remote repo and 2 peer local repos (local1 and local2).
|
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 through attribute readers
|
8
|
+
# remote, local1 and local2.
|
9
|
+
class GitHelper
|
10
|
+
include FileUtils
|
11
|
+
|
12
|
+
@@WORK_DIR = 'repo_test'
|
13
|
+
|
14
|
+
attr_reader :remote, :local1, :local2
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@wd = get_temp_dir
|
18
|
+
|
19
|
+
@remote = init_repo(@wd, 'remote')
|
20
|
+
@local1 = clone_repo(@remote, @wd, 'local1')
|
21
|
+
@local2 = clone_repo(@remote, @wd, 'local2')
|
22
|
+
end
|
23
|
+
|
24
|
+
def cleanup
|
25
|
+
rm_rf @wd
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def get_temp_dir
|
30
|
+
#Note: it's NOT a good idea to do this stuff un a subdirectory of the
|
31
|
+
#git_remote_branch repo. Trust me :-)
|
32
|
+
wd = File.expand_path( File.join( Dir::tmpdir, @@WORK_DIR) )
|
33
|
+
Dir.mkdir wd unless File.exists? wd
|
34
|
+
|
35
|
+
#Create new subdir with a random name
|
36
|
+
new_dir=''
|
37
|
+
begin
|
38
|
+
new_dir = File.join( wd, "#{rand(10000)}" )
|
39
|
+
Dir.mkdir new_dir
|
40
|
+
rescue
|
41
|
+
retry
|
42
|
+
end
|
43
|
+
|
44
|
+
new_dir
|
45
|
+
end
|
46
|
+
|
47
|
+
def init_repo(path, name)
|
48
|
+
repo_dir = File.join(path, name)
|
49
|
+
`mkdir #{repo_dir}; cd $_; git init; touch file.txt; git add .; git commit -a -m "dummy file"`
|
50
|
+
repo_dir
|
51
|
+
end
|
52
|
+
|
53
|
+
def clone_repo(origin_path, clone_path, name)
|
54
|
+
`cd #{clone_path}; git clone #{File.join(origin_path, '.git')} #{name}`
|
55
|
+
return File.join(clone_path, name)
|
56
|
+
end
|
57
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
test_dir = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'try_require'
|
8
|
+
rescue LoadError
|
9
|
+
require File.join( [test_dir] + %w{ .. vendor try_require try_require } )
|
10
|
+
end
|
11
|
+
|
12
|
+
try_require 'redgreen'
|
13
|
+
try_require 'ruby-debug'
|
14
|
+
|
15
|
+
require File.join(test_dir, 'git_helper')
|
16
|
+
require File.join( [test_dir] + %w{ .. lib git_remote_branch} )
|
17
|
+
|
18
|
+
class Test::Unit::TestCase
|
19
|
+
include GitRemoteBranch
|
20
|
+
|
21
|
+
# Passes assertion if condition is false
|
22
|
+
def assert_false(condition, message = nil)
|
23
|
+
message = "assert_false failed" unless message
|
24
|
+
assert condition == false, message
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
class GitHelperTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@g = GitHelper.new
|
8
|
+
@directories = [@g.remote, @g.local1, @g.local2]
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@g.cleanup
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_init
|
16
|
+
@directories.each do |d|
|
17
|
+
assert File.exists?(@g.remote), 'Directory for repo must be created'
|
18
|
+
assert File.exists?( File.join(@g.remote, '.git') ), 'Repo must be created'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_cleanup
|
23
|
+
@g.cleanup
|
24
|
+
|
25
|
+
@directories.each do |d|
|
26
|
+
assert_false File.exists?(@g.remote), 'Each repo directory must be destroyed after cleanup'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git_remote_branch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mathieu Martin
|
8
|
+
- Carl Mercier
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2008-07-15 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: colored
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "1.1"
|
25
|
+
version:
|
26
|
+
description: git_remote_branch is a learning tool to ease the interaction with remote branches in simple situations.
|
27
|
+
email: webmat@gmail.com
|
28
|
+
executables:
|
29
|
+
- grb
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- Rakefile
|
36
|
+
- README
|
37
|
+
- TODO
|
38
|
+
- bin/grb
|
39
|
+
- lib/git_remote_branch.rb
|
40
|
+
- lib/param_reader.rb
|
41
|
+
- test/git_helper.rb
|
42
|
+
- test/test_helper.rb
|
43
|
+
- test/unit/git_helper_test.rb
|
44
|
+
has_rdoc: false
|
45
|
+
homepage: http://github.com/webmat/git_remote_branch
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.2.0
|
67
|
+
signing_key:
|
68
|
+
specification_version: 2
|
69
|
+
summary: git_remote_branch eases the interaction with remote branches
|
70
|
+
test_files:
|
71
|
+
- test/git_helper.rb
|
72
|
+
- test/test_helper.rb
|
73
|
+
- test/unit/git_helper_test.rb
|