git-switcher 0.0.1
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/.gitignore +19 -0
- data/.travis.yml +6 -0
- data/Gemfile +11 -0
- data/Guardfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/Rakefile +32 -0
- data/bin/git-switcher +63 -0
- data/features/help_and_version.feature +20 -0
- data/features/step_definitions/git-switcher_steps.rb +21 -0
- data/features/support/env.rb +7 -0
- data/git-switcher.gemspec +50 -0
- data/lib/git-switcher.rb +17 -0
- data/lib/git-switcher/banner.rb +13 -0
- data/lib/git-switcher/copyright.rb +6 -0
- data/lib/git-switcher/menu.rb +99 -0
- data/lib/git-switcher/repo.rb +91 -0
- data/lib/git-switcher/version.rb +5 -0
- data/spec/lib/git-switcher/repo_spec.rb +9 -0
- data/spec/lib/git-switcher_spec.rb +7 -0
- data/spec/spec_helper.rb +8 -0
- metadata +378 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', :cli => '--format RSpec::Pride --tty' do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
end
|
9
|
+
|
10
|
+
guard 'cucumber', :cli => '--tags ~@wip --format Cucumber::Pride::Formatter' do
|
11
|
+
watch(%r{^features/.+\.feature$})
|
12
|
+
watch(%r{^(bin|lib)/.+$}) { 'features' }
|
13
|
+
watch(%r{^features/support/.+$}) { 'features' }
|
14
|
+
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
|
15
|
+
end
|
16
|
+
|
17
|
+
# vim:syntax=ruby
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Peter Vandenberk
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Git::Switcher
|
2
|
+
|
3
|
+
[](http://travis-ci.org/pvdb/git-switcher)
|
4
|
+
|
5
|
+
Visual CLI and REPL for easily switching between git tags and branches
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'git-switcher'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install git-switcher
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
`cd` into your favourite git repo, and run `git switcher`
|
24
|
+
|
25
|
+
It will present you with a couple of submenus, one each for:
|
26
|
+
|
27
|
+
1. all **remote** branches
|
28
|
+
1. all **local** branches
|
29
|
+
1. all **reachable** tags
|
30
|
+
|
31
|
+
*(unless any of them are empty, in which case the corresponding submenu is omitted)*
|
32
|
+
|
33
|
+
REMOTE BRANCHES
|
34
|
+
|
35
|
+
[1] origin/aaaaaa
|
36
|
+
[2] origin/bbbbbbb
|
37
|
+
[3] origin/cccccccc
|
38
|
+
[4] origin/ddddd
|
39
|
+
[5] origin/eeeeeee
|
40
|
+
[6] origin/master ***
|
41
|
+
[7] origin/ffffff
|
42
|
+
[8] origin/gggggggggg
|
43
|
+
[9] origin/pvandenb
|
44
|
+
[10] origin/hhhh
|
45
|
+
|
46
|
+
LOCAL BRANCHES
|
47
|
+
|
48
|
+
[11] master ***
|
49
|
+
[12] pvandenb
|
50
|
+
|
51
|
+
REACHABLE TAGS
|
52
|
+
|
53
|
+
[a] kernel_open_gets
|
54
|
+
[b] file_open_each
|
55
|
+
[c] file_foreach
|
56
|
+
[d] regexp_compile_match
|
57
|
+
[e] named_capture_group
|
58
|
+
[f] use_args_gets
|
59
|
+
[g] last_read_line
|
60
|
+
[h] ruby_minus_n
|
61
|
+
[i] ruby_minus_p
|
62
|
+
|
63
|
+
Your selection > _
|
64
|
+
|
65
|
+
If the current git `HEAD` corresponds to any of the listed branches or tags, then the corresponding menu items are highlighted with `***`
|
66
|
+
|
67
|
+
Each menu item is prefixed with a shortcut key, either a *number* (for branches) or else a *letter* (for tags).
|
68
|
+
|
69
|
+
It will next prompt you for your selection as follows:
|
70
|
+
|
71
|
+
Your selection > _
|
72
|
+
|
73
|
+
Enter one of the shortcut keys to quickly do a `git checkout` of the corresponding branch or tag.
|
74
|
+
|
75
|
+
It will then redraw the menu, so that the selected branch or tag is now highlighted, and so that the list of reachable tags is updated correspondingly.
|
76
|
+
|
77
|
+
`git switcher` will keep looping as described above, until you enter `quit` or else interrupt the script with either `^D` or `^C`.
|
78
|
+
|
79
|
+
## Default selection
|
80
|
+
|
81
|
+
To make it easy and convenient to sequentially loop through all branches or tags, `git switcher` will remember your previous selection, and offer the next menu item as the default.
|
82
|
+
|
83
|
+
For example, if you previously selected `11` to switch to the local `master` branch, then the next prompt presented by `git switcher` will be:
|
84
|
+
|
85
|
+
([12] pvandenb) > _
|
86
|
+
|
87
|
+
To quickly switch to the `pvandenb` branch, just press `enter` *(without having to enter the corresponding shortcut key)*.
|
88
|
+
|
89
|
+
## Contributing
|
90
|
+
|
91
|
+
1. Fork it
|
92
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
93
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
94
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
95
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
task :default => [:test]
|
4
|
+
task :test => [:spec, :features]
|
5
|
+
|
6
|
+
task :gemspec do
|
7
|
+
@gemspec ||= eval(File.read(Dir["*.gemspec"].first))
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Validate the gemspec"
|
11
|
+
task :validate => :gemspec do
|
12
|
+
@gemspec.validate
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'rspec'
|
16
|
+
require 'rspec/core/rake_task'
|
17
|
+
|
18
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
19
|
+
t.rspec_opts = "--format d --color"
|
20
|
+
end
|
21
|
+
|
22
|
+
task :rspec => [:spec]
|
23
|
+
|
24
|
+
require 'cucumber'
|
25
|
+
require 'cucumber/rake/task'
|
26
|
+
|
27
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
28
|
+
t.cucumber_opts = "features --format pretty --tags ~@wip"
|
29
|
+
end
|
30
|
+
|
31
|
+
task :cucumber => [:features]
|
32
|
+
|
data/bin/git-switcher
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'git-switcher'
|
7
|
+
rescue LoadError
|
8
|
+
require 'rubygems'
|
9
|
+
require 'git-switcher'
|
10
|
+
end
|
11
|
+
|
12
|
+
options = Trollop::options do
|
13
|
+
|
14
|
+
version Git::Switcher::COPYRIGHT
|
15
|
+
banner Git::Switcher::BANNER
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
raise "TTY only!" unless STDIN.tty? && STDOUT.tty?
|
20
|
+
|
21
|
+
repo = Git::Switcher::Repo.new(Git::Switcher::Repo.discover(Dir.pwd))
|
22
|
+
|
23
|
+
# this holds the menu item that will be selected
|
24
|
+
# if the user just presses "enter" ... typically
|
25
|
+
# this will be "the next thing on the list", ie.
|
26
|
+
# the next branch or the next tag on the list...
|
27
|
+
default_menu_item = nil
|
28
|
+
|
29
|
+
running = true ; while running
|
30
|
+
|
31
|
+
# clear the screen (bit of a hack)
|
32
|
+
print "\e[H\e[2J"
|
33
|
+
|
34
|
+
# generate and print the repo menu
|
35
|
+
puts(menu = Menu.for(repo))
|
36
|
+
|
37
|
+
# print prompt, read response and execute command corresponding to the menu item
|
38
|
+
begin
|
39
|
+
puts ; print default_menu_item ? "(#{default_menu_item}) > " : 'Your selection > '
|
40
|
+
if gets
|
41
|
+
case (response = $_.chomp.strip)
|
42
|
+
when 'quit'
|
43
|
+
running = false
|
44
|
+
when *menu.shortcut_keys, ''
|
45
|
+
if (menu_item = menu[response] || default_menu_item)
|
46
|
+
# execute the command for the selected menu item
|
47
|
+
`#{menu_item.command}`
|
48
|
+
# store the menu item that succeeds the selected one
|
49
|
+
default_menu_item = menu_item.next
|
50
|
+
end
|
51
|
+
else
|
52
|
+
# invalid command... ignore!
|
53
|
+
end
|
54
|
+
else
|
55
|
+
puts "^D" ; running = false # user has pressed ^D
|
56
|
+
end
|
57
|
+
rescue Interrupt
|
58
|
+
puts ; running = false # user has pressed ^C
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
# That's all, Folks!
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Help Me I've Got Versionitis
|
2
|
+
|
3
|
+
Scenario: get help for the main script
|
4
|
+
|
5
|
+
When I get help for "git-switcher"
|
6
|
+
Then the exit status should be 0
|
7
|
+
And the banner should be present
|
8
|
+
And the banner should include the version
|
9
|
+
And the banner should document that this app takes options
|
10
|
+
And the following options should be documented:
|
11
|
+
| --version, -v: |
|
12
|
+
| --help, -h: |
|
13
|
+
|
14
|
+
Scenario: get the version of the main script
|
15
|
+
|
16
|
+
When I get the version of "git-switcher"
|
17
|
+
Then the exit status should be 0
|
18
|
+
And the output should include the version
|
19
|
+
And the output should include the app name
|
20
|
+
And the output should include a copyright notice
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#
|
2
|
+
# Methadone/Aruba "extensions"/"customizations"
|
3
|
+
#
|
4
|
+
|
5
|
+
When /^I get the version of "([^"]*)"$/ do |script_name|
|
6
|
+
@script_name = script_name
|
7
|
+
step %(I run `#{script_name} --version`)
|
8
|
+
end
|
9
|
+
|
10
|
+
Then /^the output should include the version$/ do
|
11
|
+
step %(the output should match /v\\d+\\.\\d+\\.\\d+/)
|
12
|
+
end
|
13
|
+
|
14
|
+
Then /^the output should include the app name$/ do
|
15
|
+
step %(the output should match /#{Regexp.escape(@script_name)}/)
|
16
|
+
end
|
17
|
+
|
18
|
+
Then /^the output should include a copyright notice$/ do
|
19
|
+
step %(the output should match /Copyright \\(c\\) [\\d]{4} [[\\w]+]+/)
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'git-switcher/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "git-switcher"
|
8
|
+
gem.version = Git::Switcher::VERSION
|
9
|
+
gem.authors = ["Peter Vandenberk"]
|
10
|
+
gem.email = ["pvandenberk@mac.com"]
|
11
|
+
gem.description = %q{Git command that implements a visual CLI and REPL for easily switching between git tags and branches}
|
12
|
+
gem.summary = %q{Visual CLI and REPL for switching between git tags and branches}
|
13
|
+
gem.homepage = "https://github.com/pvdb/git-switcher"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency('methadone')
|
21
|
+
gem.add_dependency('rugged')
|
22
|
+
gem.add_dependency('trollop')
|
23
|
+
|
24
|
+
# for developing
|
25
|
+
gem.add_development_dependency('rdoc')
|
26
|
+
gem.add_development_dependency('awesome_print')
|
27
|
+
|
28
|
+
# for debugging
|
29
|
+
gem.add_development_dependency('pry')
|
30
|
+
gem.add_development_dependency('pry-debugger')
|
31
|
+
gem.add_development_dependency('pry-stack_explorer')
|
32
|
+
|
33
|
+
# for testing
|
34
|
+
gem.add_development_dependency('rspec')
|
35
|
+
gem.add_development_dependency('cucumber')
|
36
|
+
gem.add_development_dependency('aruba')
|
37
|
+
|
38
|
+
# for monitoring
|
39
|
+
gem.add_development_dependency('guard')
|
40
|
+
gem.add_development_dependency('growl')
|
41
|
+
gem.add_development_dependency('rb-fsevent')
|
42
|
+
gem.add_development_dependency('rb-readline')
|
43
|
+
|
44
|
+
# for TDD/BDD/CI
|
45
|
+
gem.add_development_dependency('guard-rspec')
|
46
|
+
gem.add_development_dependency('guard-cucumber')
|
47
|
+
gem.add_development_dependency('rspec-pride')
|
48
|
+
gem.add_development_dependency('cucumber-pride')
|
49
|
+
|
50
|
+
end
|
data/lib/git-switcher.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'rugged'
|
4
|
+
require 'trollop'
|
5
|
+
|
6
|
+
require 'git-switcher/version'
|
7
|
+
require 'git-switcher/banner'
|
8
|
+
require 'git-switcher/copyright'
|
9
|
+
|
10
|
+
require 'git-switcher/repo'
|
11
|
+
require 'git-switcher/menu'
|
12
|
+
|
13
|
+
module Git
|
14
|
+
module Switcher
|
15
|
+
# Your code goes here...
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class Menu
|
2
|
+
|
3
|
+
Struct.new("Submenu", :label, :menu_items) do
|
4
|
+
def to_s
|
5
|
+
"\n\t#{label}\n\n" + menu_items.join("\n")
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Struct.new("MenuItem", :shortcut, :label, :highlight, :command, :next) do
|
10
|
+
def to_s
|
11
|
+
"[%s]\t%s%s" % [shortcut.key, label, highlight ? ' ***' : '']
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Struct.new("Shortcut", :key, :calc_next_key) do
|
16
|
+
def next
|
17
|
+
self.class.new(self.calc_next_key.call(self.key), self.calc_next_key)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :submenus
|
22
|
+
attr_accessor :menu_items
|
23
|
+
|
24
|
+
def initialize repo
|
25
|
+
@repo = repo # a git repository!
|
26
|
+
@submenus = [] # addition-ordered!
|
27
|
+
@menu_items = {} # keyed on shortcut
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
@submenus.join("\n")
|
32
|
+
end
|
33
|
+
|
34
|
+
def [] key
|
35
|
+
@menu_items[key]
|
36
|
+
end
|
37
|
+
|
38
|
+
def shortcut_keys
|
39
|
+
@menu_items.keys
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.for repo
|
43
|
+
self.new(repo).tap { |menu|
|
44
|
+
|
45
|
+
shortcut = Struct::Shortcut.new('1', lambda { |key| (key.to_i + 1).to_s })
|
46
|
+
menu.add_submenu_for("REMOTE BRANCHES", repo.remote_branches, shortcut) unless repo.remote_branches.empty?
|
47
|
+
|
48
|
+
shortcut = Struct::Shortcut.new((repo.remote_branches.count + 1).to_s, lambda { |key| (key.to_i + 1).to_s })
|
49
|
+
menu.add_submenu_for("LOCAL BRANCHES", repo.local_branches, shortcut) unless repo.local_branches.empty?
|
50
|
+
|
51
|
+
shortcut = Struct::Shortcut.new('a', lambda { |key| (key.ord + 1).chr })
|
52
|
+
menu.add_submenu_for("REACHABLE TAGS", repo.reachable_tags, shortcut) unless repo.reachable_tags.empty?
|
53
|
+
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_submenu_for label, refs, shortcut
|
58
|
+
|
59
|
+
# calculate the new submenu: one menu item for each one of the refs
|
60
|
+
submenu = Struct::Submenu.new(label, menu_items_for(refs, shortcut))
|
61
|
+
|
62
|
+
# add the submenu to the main menu
|
63
|
+
self.submenus << submenu
|
64
|
+
|
65
|
+
# register each menu item of the new submenu via its shortcut key
|
66
|
+
submenu.menu_items.each do |menu_item|
|
67
|
+
self.menu_items[menu_item.shortcut.key] = menu_item
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def menu_items_for refs, shortcut
|
73
|
+
|
74
|
+
previous_menu_item = nil
|
75
|
+
next_shortcut = shortcut
|
76
|
+
|
77
|
+
refs.map { |ref|
|
78
|
+
|
79
|
+
menu_item = Struct::MenuItem.new(
|
80
|
+
next_shortcut,
|
81
|
+
abbreviated_name = @repo.abbreviated_name(ref),
|
82
|
+
@repo.current_head?(ref),
|
83
|
+
"git checkout #{abbreviated_name}",
|
84
|
+
nil
|
85
|
+
)
|
86
|
+
|
87
|
+
# link the menu items together, to enable default selection
|
88
|
+
previous_menu_item and previous_menu_item.next = menu_item
|
89
|
+
|
90
|
+
previous_menu_item = menu_item
|
91
|
+
next_shortcut = next_shortcut.next
|
92
|
+
|
93
|
+
menu_item
|
94
|
+
|
95
|
+
}
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'rugged'
|
2
|
+
|
3
|
+
class Git::Switcher::Repo < Rugged::Repository
|
4
|
+
|
5
|
+
def repo
|
6
|
+
# a bug/feature in Rugged prevents us from using instances of a subclass of Rugged::Repository
|
7
|
+
# in certain methods/places; instead it insists on an instance of Rugged::Repository itself...
|
8
|
+
# (meaning we can't use `self` on those occasions!) where is Barbara Liskov when you need her?
|
9
|
+
@repo ||= Rugged::Repository.new(self.path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def current_branch
|
13
|
+
Rugged::Reference.lookup(self, 'HEAD').target.scan(/\Arefs\/heads\/(.*)\Z/).flatten.first
|
14
|
+
end
|
15
|
+
|
16
|
+
def current_head? ref
|
17
|
+
target('HEAD') == target(ref)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reachable? ref
|
21
|
+
self.class.reachable? target('HEAD'), target(ref)
|
22
|
+
end
|
23
|
+
|
24
|
+
def abbreviated_name ref
|
25
|
+
ref.gsub(/\Arefs\/(remotes|heads|tags)\//, '')
|
26
|
+
end
|
27
|
+
|
28
|
+
# remote branches
|
29
|
+
|
30
|
+
def remote_branches
|
31
|
+
self.refs.find_all { |ref| ref =~ /\Arefs\/remotes\// && ref !~ /\/HEAD\Z/ }
|
32
|
+
end
|
33
|
+
|
34
|
+
def remote_branch_name ref
|
35
|
+
ref.gsub(/\Arefs\/remotes\//, '')
|
36
|
+
end
|
37
|
+
|
38
|
+
def remote_branch_names
|
39
|
+
remote_branches.map { |ref| remote_branch_name(ref) }
|
40
|
+
end
|
41
|
+
|
42
|
+
# local branches
|
43
|
+
|
44
|
+
def local_branches
|
45
|
+
self.refs.find_all { |ref| ref =~ /\Arefs\/heads\// }
|
46
|
+
end
|
47
|
+
|
48
|
+
def local_branch_name ref
|
49
|
+
ref.gsub(/\Arefs\/heads\//, '')
|
50
|
+
end
|
51
|
+
|
52
|
+
def local_branch_names
|
53
|
+
local_branches.map { |ref| local_branch_name(ref) }
|
54
|
+
end
|
55
|
+
|
56
|
+
# tags
|
57
|
+
|
58
|
+
def tags
|
59
|
+
self.refs.find_all { |ref| ref =~ /\Arefs\/tags\// }
|
60
|
+
end
|
61
|
+
|
62
|
+
def reachable_tags # time-ordered, as well
|
63
|
+
tags.find_all { |tag| reachable? tag }.sort { |first_tag, second_tag|
|
64
|
+
target(first_tag).time <=> target(second_tag).time
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def tag_name ref
|
69
|
+
ref.gsub(/\Arefs\/tags\//, '')
|
70
|
+
end
|
71
|
+
|
72
|
+
def tag_names
|
73
|
+
tags.map { |ref| tag_name(ref) }
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def target ref
|
79
|
+
# TODO read up on git tagging, ie. tag another tag, ad infinitum (?)
|
80
|
+
target = self.repo.lookup(Rugged::Reference.lookup(self, ref).resolve.target)
|
81
|
+
target = target.target if target.is_a? Rugged::Tag
|
82
|
+
target
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.reachable? current_commit, past_commit
|
86
|
+
(current_commit == past_commit) || begin
|
87
|
+
current_commit.parents.any? { |parent| self.reachable? parent, past_commit }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,378 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-switcher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Peter Vandenberk
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: methadone
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rugged
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: trollop
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rdoc
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: awesome_print
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: pry
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: pry-debugger
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: pry-stack_explorer
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: rspec
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: cucumber
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: aruba
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
- !ruby/object:Gem::Dependency
|
191
|
+
name: guard
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
type: :development
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
- !ruby/object:Gem::Dependency
|
207
|
+
name: growl
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
209
|
+
none: false
|
210
|
+
requirements:
|
211
|
+
- - ! '>='
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '0'
|
214
|
+
type: :development
|
215
|
+
prerelease: false
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
none: false
|
218
|
+
requirements:
|
219
|
+
- - ! '>='
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
- !ruby/object:Gem::Dependency
|
223
|
+
name: rb-fsevent
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
225
|
+
none: false
|
226
|
+
requirements:
|
227
|
+
- - ! '>='
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
none: false
|
234
|
+
requirements:
|
235
|
+
- - ! '>='
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
- !ruby/object:Gem::Dependency
|
239
|
+
name: rb-readline
|
240
|
+
requirement: !ruby/object:Gem::Requirement
|
241
|
+
none: false
|
242
|
+
requirements:
|
243
|
+
- - ! '>='
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: '0'
|
246
|
+
type: :development
|
247
|
+
prerelease: false
|
248
|
+
version_requirements: !ruby/object:Gem::Requirement
|
249
|
+
none: false
|
250
|
+
requirements:
|
251
|
+
- - ! '>='
|
252
|
+
- !ruby/object:Gem::Version
|
253
|
+
version: '0'
|
254
|
+
- !ruby/object:Gem::Dependency
|
255
|
+
name: guard-rspec
|
256
|
+
requirement: !ruby/object:Gem::Requirement
|
257
|
+
none: false
|
258
|
+
requirements:
|
259
|
+
- - ! '>='
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: '0'
|
262
|
+
type: :development
|
263
|
+
prerelease: false
|
264
|
+
version_requirements: !ruby/object:Gem::Requirement
|
265
|
+
none: false
|
266
|
+
requirements:
|
267
|
+
- - ! '>='
|
268
|
+
- !ruby/object:Gem::Version
|
269
|
+
version: '0'
|
270
|
+
- !ruby/object:Gem::Dependency
|
271
|
+
name: guard-cucumber
|
272
|
+
requirement: !ruby/object:Gem::Requirement
|
273
|
+
none: false
|
274
|
+
requirements:
|
275
|
+
- - ! '>='
|
276
|
+
- !ruby/object:Gem::Version
|
277
|
+
version: '0'
|
278
|
+
type: :development
|
279
|
+
prerelease: false
|
280
|
+
version_requirements: !ruby/object:Gem::Requirement
|
281
|
+
none: false
|
282
|
+
requirements:
|
283
|
+
- - ! '>='
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '0'
|
286
|
+
- !ruby/object:Gem::Dependency
|
287
|
+
name: rspec-pride
|
288
|
+
requirement: !ruby/object:Gem::Requirement
|
289
|
+
none: false
|
290
|
+
requirements:
|
291
|
+
- - ! '>='
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '0'
|
294
|
+
type: :development
|
295
|
+
prerelease: false
|
296
|
+
version_requirements: !ruby/object:Gem::Requirement
|
297
|
+
none: false
|
298
|
+
requirements:
|
299
|
+
- - ! '>='
|
300
|
+
- !ruby/object:Gem::Version
|
301
|
+
version: '0'
|
302
|
+
- !ruby/object:Gem::Dependency
|
303
|
+
name: cucumber-pride
|
304
|
+
requirement: !ruby/object:Gem::Requirement
|
305
|
+
none: false
|
306
|
+
requirements:
|
307
|
+
- - ! '>='
|
308
|
+
- !ruby/object:Gem::Version
|
309
|
+
version: '0'
|
310
|
+
type: :development
|
311
|
+
prerelease: false
|
312
|
+
version_requirements: !ruby/object:Gem::Requirement
|
313
|
+
none: false
|
314
|
+
requirements:
|
315
|
+
- - ! '>='
|
316
|
+
- !ruby/object:Gem::Version
|
317
|
+
version: '0'
|
318
|
+
description: Git command that implements a visual CLI and REPL for easily switching
|
319
|
+
between git tags and branches
|
320
|
+
email:
|
321
|
+
- pvandenberk@mac.com
|
322
|
+
executables:
|
323
|
+
- git-switcher
|
324
|
+
extensions: []
|
325
|
+
extra_rdoc_files: []
|
326
|
+
files:
|
327
|
+
- .gitignore
|
328
|
+
- .travis.yml
|
329
|
+
- Gemfile
|
330
|
+
- Guardfile
|
331
|
+
- LICENSE.txt
|
332
|
+
- README.md
|
333
|
+
- Rakefile
|
334
|
+
- bin/git-switcher
|
335
|
+
- features/help_and_version.feature
|
336
|
+
- features/step_definitions/git-switcher_steps.rb
|
337
|
+
- features/support/env.rb
|
338
|
+
- git-switcher.gemspec
|
339
|
+
- lib/git-switcher.rb
|
340
|
+
- lib/git-switcher/banner.rb
|
341
|
+
- lib/git-switcher/copyright.rb
|
342
|
+
- lib/git-switcher/menu.rb
|
343
|
+
- lib/git-switcher/repo.rb
|
344
|
+
- lib/git-switcher/version.rb
|
345
|
+
- spec/lib/git-switcher/repo_spec.rb
|
346
|
+
- spec/lib/git-switcher_spec.rb
|
347
|
+
- spec/spec_helper.rb
|
348
|
+
homepage: https://github.com/pvdb/git-switcher
|
349
|
+
licenses: []
|
350
|
+
post_install_message:
|
351
|
+
rdoc_options: []
|
352
|
+
require_paths:
|
353
|
+
- lib
|
354
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
355
|
+
none: false
|
356
|
+
requirements:
|
357
|
+
- - ! '>='
|
358
|
+
- !ruby/object:Gem::Version
|
359
|
+
version: '0'
|
360
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
361
|
+
none: false
|
362
|
+
requirements:
|
363
|
+
- - ! '>='
|
364
|
+
- !ruby/object:Gem::Version
|
365
|
+
version: '0'
|
366
|
+
requirements: []
|
367
|
+
rubyforge_project:
|
368
|
+
rubygems_version: 1.8.24
|
369
|
+
signing_key:
|
370
|
+
specification_version: 3
|
371
|
+
summary: Visual CLI and REPL for switching between git tags and branches
|
372
|
+
test_files:
|
373
|
+
- features/help_and_version.feature
|
374
|
+
- features/step_definitions/git-switcher_steps.rb
|
375
|
+
- features/support/env.rb
|
376
|
+
- spec/lib/git-switcher/repo_spec.rb
|
377
|
+
- spec/lib/git-switcher_spec.rb
|
378
|
+
- spec/spec_helper.rb
|