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 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 webmat-git_remote_branch --source=http://gems.github.com
16
+ sudo gem install grb
17
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.
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
- Rename the remote branch by copying and deleting the old name.
61
- Checkout a new local tracking branch with the new name and delete the branch
62
- with the old name.
63
- branch_name is the new name, the old name is always the current branch's
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.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.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
- === Contributors ===
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
- Rake::TestTask.new(:test) do |t|
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
- - 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)
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
- print_welcome
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
- p = read_params(ARGV)
19
+ whisper get_welcome
13
20
 
14
21
  if p[:action] == :help
15
- print_usage
22
+ whisper get_usage
16
23
  exit 0
17
24
  end
18
25
 
@@ -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
- VERSION = '0.2.4'
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 print_welcome
59
- puts "git_remote_branch version #{VERSION}", ''
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 print_usage
63
- puts <<-HELP
94
+ def get_usage
95
+ return <<-HELP
64
96
  Usage:
65
97
 
66
- grb create branch_name [origin_server]
67
-
68
- grb delete branch_name [origin_server]
69
-
70
- grb rename branch_name [origin_server]
71
-
72
- grb track branch_name [origin_server]
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
- puts "List of operations to do to #{COMMANDS[action][:description]}:", ''
126
+ whisper "List of operations to do to #{COMMANDS[action][:description]}:", ''
96
127
  puts_cmd cmds
97
- puts ''
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
- puts ''
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
- puts "#{c}".red
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[: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
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
- #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]
17
+ return HELP_PARAMS if p[:action] == :help
12
18
 
13
- #TODO Some validation on the params
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
- p
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
- 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 :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
- def get_current_branch
45
- #This is sensitive to checkouts of branches specified with wrong case
46
- x = `git branch -l`
47
- x.each_line do |l|
48
- return l.sub("*","").strip if l =~ /\A\*/ and not l =~ /\(no branch\)/
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
data/lib/version.rb ADDED
@@ -0,0 +1,14 @@
1
+ module GitRemoteBranch
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ TINY = 6
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.').freeze
8
+ end
9
+
10
+ NAME = 'git_remote_branch'.freeze
11
+ COMPLETE_NAME = "#{NAME} #{VERSION::STRING}".freeze
12
+ COMMAND_NAME = 'grb'.freeze
13
+ SHORT_NAME = COMMAND_NAME
14
+ end
data/tasks/gem.rake ADDED
@@ -0,0 +1,73 @@
1
+ require 'yaml'
2
+
3
+ require 'rake/gempackagetask'
4
+
5
+ task :clean => :clobber_package
6
+
7
+ spec = Gem::Specification.new do |s|
8
+ s.name = GitRemoteBranch::NAME
9
+ s.version = GitRemoteBranch::VERSION::STRING
10
+ s.summary = "git_remote_branch eases the interaction with remote branches"
11
+ s.description = "git_remote_branch is a learning tool to ease the interaction with " +
12
+ "remote branches in simple situations."
13
+
14
+ s.authors = ['Mathieu Martin', 'Carl Mercier']
15
+ s.email = "webmat@gmail.com"
16
+ s.homepage = "http://github.com/webmat/git_remote_branch"
17
+ s.rubyforge_project = 'grb'
18
+
19
+ s.has_rdoc = false
20
+
21
+ s.test_files = Dir['test/**/*']
22
+ s.files = Dir['**/*'].reject{|f| f =~ /\Apkg|\Acoverage|\.gemspec\Z/}
23
+
24
+ s.executable = 'grb'
25
+ s.bindir = "bin"
26
+ s.require_path = "lib"
27
+
28
+ s.add_dependency( 'colored', '>= 1.1' )
29
+ end
30
+
31
+ #Creates clobber_package, gem, package and repackage tasks
32
+ #Note on clobber_package: fortunately, this will clobber the CODE package
33
+ Rake::GemPackageTask.new(spec) do |p|
34
+ p.gem_spec = spec
35
+ end
36
+
37
+ TAG_COMMAND = "git tag -m 'Tagging version #{GitRemoteBranch::VERSION::STRING}' -a v#{GitRemoteBranch::VERSION::STRING}"
38
+ task :tag_warn do
39
+ puts "*" * 40,
40
+ "Don't forget to tag the release:",
41
+ '',
42
+ " " + TAG_COMMAND,
43
+ '',
44
+ "or run rake tag",
45
+ "*" * 40
46
+ end
47
+ task :tag do
48
+ sh TAG_COMMAND
49
+ end
50
+ task :gem => :tag_warn
51
+
52
+ namespace :gem do
53
+ desc "Update the gemspec for GitHub's gem server"
54
+ task :github do
55
+ File.open("#{GitRemoteBranch::NAME}.gemspec", 'w'){|f| f.puts YAML::dump(spec) }
56
+ puts "gemspec generated here: #{GitRemoteBranch::NAME}.gemspec"
57
+ end
58
+
59
+ desc 'Upload gem to rubyforge.org'
60
+ task :rubyforge => :gem do
61
+ sh 'rubyforge login'
62
+ sh "rubyforge add_release grb grb 'release #{GitRemoteBranch::VERSION::STRING}' pkg/#{spec.full_name}.gem"
63
+ sh "rubyforge add_file grb grb #{GitRemoteBranch::VERSION::STRING} pkg/#{spec.full_name}.gem"
64
+ end
65
+ end
66
+
67
+ task :install => [:clean, :gem] do
68
+ sh "#{SUDO} gem install pkg/#{spec.full_name}.gem"
69
+ end
70
+
71
+ task :uninstall do
72
+ sh "#{SUDO} gem uninstall -v #{GitRemoteBranch::VERSION::STRING} -x #{GitRemoteBranch::NAME}"
73
+ end
data/tasks/test.rake ADDED
@@ -0,0 +1,21 @@
1
+ require 'rake/testtask'
2
+
3
+ desc "Run all tests"
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.pattern = 'test/**/*_test.rb'
6
+ t.verbose = true
7
+ end
8
+
9
+ namespace :test do
10
+ desc "Run functional tests"
11
+ Rake::TestTask.new(:functional) do |t|
12
+ t.pattern = 'test/functional/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc "Run unit tests"
17
+ Rake::TestTask.new(:unit) do |t|
18
+ t.pattern = 'test/unit/**/*_test.rb'
19
+ t.verbose = true
20
+ end
21
+ end