git-browse-remote 0.0.2 → 0.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +5 -0
- data/bin/git-browse-remote +2 -143
- data/git-browse-remote.gemspec +27 -0
- data/lib/git/browse/remote.rb +2 -0
- data/lib/git/browse/remote/core.rb +176 -0
- data/lib/git/browse/remote/git.rb +36 -0
- data/lib/git/browse/remote/runner.rb +49 -0
- data/lib/git/browse/remote/version.rb +7 -0
- data/spec/bin_spec.rb +333 -0
- data/spec/lib/git/browse/remote/core_spec.rb +159 -0
- metadata +128 -13
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3d53544ee6d46516eacca0cdffd3d41717e550c1
|
4
|
+
data.tar.gz: c4a7bcac64a6a4d730500c9b915cffca91a8abe5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 50e226a70a929a512e1ae9d7bf24a9b16b2386a6f7f8c2b7d75c31e9485e056ba9fc8ce197e033895cfe7b7ce95d0551ba560b2470eabef510b910893c3a3016
|
7
|
+
data.tar.gz: 453d60928880551b838853267590d04879c8d81a123df8db78daa43ae8fbb0fa2635fa186d649ed620b62839e896ea2925fdbc77801ac260d5d4df06bc10fbc9
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 motemen
|
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,74 @@
|
|
1
|
+
git-browse-remote [](https://travis-ci.org/motemen/git-browse-remote)
|
2
|
+
=================
|
3
|
+
|
4
|
+
`git-browse-remote` helps viewing remote repositories e.g. GitHub in your browser.
|
5
|
+
|
6
|
+
Usage
|
7
|
+
-----
|
8
|
+
|
9
|
+
```
|
10
|
+
git browse-remote [-r|--remote <remote>] [--top|--rev|--ref] [-L <n> [<commit> | <remote>] [<file>]
|
11
|
+
```
|
12
|
+
|
13
|
+
`git-browse-remote` opens your web browser by `git web--browse` to show current repository in browser.
|
14
|
+
|
15
|
+
`git-browse-remote` depends on what commit/ref `HEAD` points (or you supplied by an argument), such as:
|
16
|
+
|
17
|
+
* When on "master", opens repository's top page ("top" mode)
|
18
|
+
* e.g. opens https://github.com/motemen/git-browse-remote
|
19
|
+
* When on another branch/tag, opens repository's branch/tag page ("ref" mode)
|
20
|
+
* e.g. opens https://github.com/motemen/git-browse-remote/tree/master
|
21
|
+
* Otherwise, opens repository's commit page ("rev" mode)
|
22
|
+
* e.g. opens https://github.com/motemen/git-browse-remote/commit/04f7c64ba9d524cf311a673ddce5722b2441e2ea
|
23
|
+
|
24
|
+
As a special case, if <var>commit</var> is invalid and an valid remote name, that remore repository's page is opened.
|
25
|
+
|
26
|
+
How to set up
|
27
|
+
-------------
|
28
|
+
|
29
|
+
`git browse-remote` stores url mapping in ~/.gitconfig.
|
30
|
+
To initialize this, execute with `--init` option.
|
31
|
+
|
32
|
+
```
|
33
|
+
% git browse-remote --init
|
34
|
+
Writing config for github.com...
|
35
|
+
Mappings generated:
|
36
|
+
browse-remote.github.com.top https://{host}/{path}
|
37
|
+
browse-remote.github.com.ref https://{host}/{path}/tree/{short_ref}
|
38
|
+
browse-remote.github.com.rev https://{host}/{path}/commit/{commit}
|
39
|
+
browse-remote.github.com.file https://{host}/{path}/blob/{short_rev}/{file}{line && "#L%d" % line}
|
40
|
+
```
|
41
|
+
|
42
|
+
Execute `git config browse-remote.<host>.{top|ref|rev} <url template>`
|
43
|
+
to register other hosts mappings.
|
44
|
+
|
45
|
+
Especially, if you have a GitHub Enterprise repository, run
|
46
|
+
|
47
|
+
```
|
48
|
+
% git browse-remote --init <ghe host>=github
|
49
|
+
```
|
50
|
+
|
51
|
+
to easyly setup url mappings. `--init <host>=gitweb` is also available.
|
52
|
+
|
53
|
+
Variables available in url template
|
54
|
+
-----------------------------------
|
55
|
+
|
56
|
+
* `host` (eg. "github.com")
|
57
|
+
* `path` (eg. "motemen/git-browse-remote")
|
58
|
+
* Sliceable, subscribable like an `Array`
|
59
|
+
* `ref` (eg. "refs/heads/master")
|
60
|
+
* `short_ref` (eg. "master")
|
61
|
+
* `commit` (eg. "04f7c64ba9d524cf311a673ddce5722b2441e2ea")
|
62
|
+
* `short_commit` (eg. "04f7c64b")
|
63
|
+
* `rev` (ref or commit)
|
64
|
+
* `short_rev` (short_ref or short_commit)
|
65
|
+
* `file` (eg. "bin/git-browse-remote")
|
66
|
+
* `line` (eg. 30)
|
67
|
+
|
68
|
+
## Contributing
|
69
|
+
|
70
|
+
1. Fork it
|
71
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
72
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
73
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
74
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/git-browse-remote
CHANGED
@@ -1,146 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
# git browse-remote [-r|--remote <remote>] [--top|--rev|--ref] [-L <n>] [<commit>] [<file>]
|
5
|
-
#
|
3
|
+
require 'git/browse/remote'
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
class Path < Array
|
10
|
-
def to_s
|
11
|
-
join('/')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
remote = nil
|
16
|
-
mode = nil
|
17
|
-
file = nil
|
18
|
-
line = nil
|
19
|
-
|
20
|
-
# Variables available:
|
21
|
-
# * host (eg. "github.com")
|
22
|
-
# * path - Sliceable like an Array (eg. "motemen/git-browse-remote")
|
23
|
-
# * ref (eg. "refs/heads/master")
|
24
|
-
# * short_ref (eg. "master")
|
25
|
-
# * commit (eg. "04f7c64ba9d524cf311a673ddce5722b2441e2ea")
|
26
|
-
# * short_commit (eg. "04f7c64b")
|
27
|
-
# * rev (ref or commit)
|
28
|
-
# * short_rev (short_ref or short_commit)
|
29
|
-
# * file (eg. "bin/git-browse-remote")
|
30
|
-
# * line (eg. 30)
|
31
|
-
MAPPING_RECIPES = {
|
32
|
-
:github => {
|
33
|
-
:top => 'https://{host}/{path}',
|
34
|
-
:ref => 'https://{host}/{path}/tree/{short_ref}',
|
35
|
-
:rev => 'https://{host}/{path}/commit/{commit}',
|
36
|
-
:file => 'https://{host}/{path}/blob/{short_rev}/{file}{line && "#L%d" % line}'
|
37
|
-
},
|
38
|
-
|
39
|
-
:gitweb => {
|
40
|
-
:top => 'http://{host}/?p={path[-2..-1]}.git',
|
41
|
-
:ref => 'http://{host}/?p={path[-2..-1]}.git;h={ref}',
|
42
|
-
:rev => 'http://{host}/?p={path[-2..-1]}.git;a=commit;h={ref}',
|
43
|
-
# XXX
|
44
|
-
# I don't know file url of gitweb...
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
OptionParser.new do |opt|
|
49
|
-
opt.banner = 'git browse-remote [options] [<commit> | <remote>]'
|
50
|
-
opt.on('-r', '--remote=<remote>', 'specify remote') { |r| remote = r }
|
51
|
-
|
52
|
-
opt.on('--top', 'open `top` page') { mode = :top }
|
53
|
-
opt.on('--rev', 'open `rev` page') { mode = :rev }
|
54
|
-
opt.on('--ref', 'open `ref` page') { mode = :ref }
|
55
|
-
opt.on('--init [<host>=<recipe>]', 'initialize default url mappings') do |config|
|
56
|
-
if config
|
57
|
-
host, name = *config.split(/=/, 2)
|
58
|
-
else
|
59
|
-
host, name = 'github.com', 'github'
|
60
|
-
end
|
61
|
-
|
62
|
-
STDERR.puts "Writing config for #{host}..."
|
63
|
-
|
64
|
-
mapping = MAPPING_RECIPES[name.to_sym] or abort "Recipe '#{name}' not found"
|
65
|
-
mapping.each do |mode,template|
|
66
|
-
system %Q(git config --global browse-remote.#{host}.#{mode} '#{template}')
|
67
|
-
end
|
68
|
-
|
69
|
-
STDERR.puts 'Mappings generated:'
|
70
|
-
exec "git config --get-regexp ^browse-remote\\.#{host}\\."
|
71
|
-
end
|
72
|
-
opt.on('-L <n>', 'specify line number (only meaningful on file mode)', Integer) { |n| line = n }
|
73
|
-
opt.parse!(ARGV)
|
74
|
-
end
|
75
|
-
|
76
|
-
target, file = *ARGV[0..1]
|
77
|
-
|
78
|
-
# handle git browse-remote <file>
|
79
|
-
# TODO file exists and also is a valid ref/origin
|
80
|
-
if target && !file && File.exists?(target)
|
81
|
-
target, file = nil, target
|
82
|
-
end
|
83
|
-
|
84
|
-
target ||= `git symbolic-ref -q HEAD`[/.+/]
|
85
|
-
|
86
|
-
if target
|
87
|
-
if `git rev-parse --verify --quiet #{target}` && $? == 0
|
88
|
-
# valid ref
|
89
|
-
ref = `git rev-parse --symbolic-full-name #{target}`.chomp
|
90
|
-
elsif `git config --get remote.#{target}.url`.chomp.empty? == false
|
91
|
-
# not a valid ref, but valid remote
|
92
|
-
ref = 'master'
|
93
|
-
remote = target
|
94
|
-
target = nil
|
95
|
-
else
|
96
|
-
abort "Not a valid ref or remote: #{target}"
|
97
|
-
end
|
98
|
-
else
|
99
|
-
ref = `git name-rev --name-only HEAD`.chomp.sub(%r(\^0$), '') # some workaround for ^0
|
100
|
-
end
|
101
|
-
|
102
|
-
if ref == 'HEAD'
|
103
|
-
ref = nil
|
104
|
-
short_ref = nil
|
105
|
-
else
|
106
|
-
short_ref = ref.sub(%r(^refs/), '')
|
107
|
-
|
108
|
-
if short_ref.sub!(%r(^heads/), '')
|
109
|
-
mode ||= short_ref == 'master' ? :top : :ref
|
110
|
-
end
|
111
|
-
|
112
|
-
if short_ref.sub!(%r(^tags/), '')
|
113
|
-
mode ||= :ref
|
114
|
-
end
|
115
|
-
|
116
|
-
if short_ref.sub!(%r(^remotes/([^/]+)/), '')
|
117
|
-
remote ||= $1
|
118
|
-
mode ||= short_ref == 'master' ? :top : :ref
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
commit = `git rev-parse #{target || 'HEAD'}`.chomp
|
124
|
-
short_commit = `git rev-parse --short #{target || 'HEAD'}`.chomp
|
125
|
-
|
126
|
-
# `rev` will be raw sha1 if --rev is specified explicitly
|
127
|
-
rev = mode == :rev ? commit : ref || commit
|
128
|
-
short_rev = mode == :rev ? short_commit : short_ref || short_commit
|
129
|
-
|
130
|
-
mode = :file if file
|
131
|
-
|
132
|
-
remote ||= 'origin'
|
133
|
-
mode ||= :rev
|
134
|
-
|
135
|
-
remote_url = `git config remote.#{remote}.url`[/.+/] or
|
136
|
-
abort "Could not get remote url: #{remote}"
|
137
|
-
|
138
|
-
host, *path = remote_url.sub(%r(^\w+://), '').sub(/^[\w-]+@/, '').split(/[\/:]+/)
|
139
|
-
path.last.sub!(/\.git$/, '')
|
140
|
-
path = Path.new(path)
|
141
|
-
|
142
|
-
template = `git config --get browse-remote.#{host}.#{mode}`[/.+/] or
|
143
|
-
abort "No '#{mode}' mapping found for #{host} (maybe `git browse-remote --init` required)"
|
144
|
-
|
145
|
-
url = template.gsub(/\{(.+?)\}/) { |m| eval($1) }
|
146
|
-
exec 'git', 'web--browse', url
|
5
|
+
Git::Browse::Remote::Runner.new(ARGV).run
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'git/browse/remote/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "git-browse-remote"
|
8
|
+
spec.version = Git::Browse::Remote::VERSION
|
9
|
+
spec.authors = ["motemen"]
|
10
|
+
spec.email = ["motemen@gmail.com"]
|
11
|
+
spec.summary = 'Open web browser to view remote Git repositories'
|
12
|
+
spec.homepage = 'https://github.com/motemen/git-browse-remote'
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_development_dependency 'rspec', '~> 2'
|
23
|
+
spec.add_development_dependency 'simplecov', '0.7.1'
|
24
|
+
spec.add_development_dependency 'guard'
|
25
|
+
spec.add_development_dependency 'guard-rspec'
|
26
|
+
spec.add_development_dependency 'terminal-notifier-guard'
|
27
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'git/browse/remote/git'
|
2
|
+
|
3
|
+
module Git::Browse::Remote
|
4
|
+
class Path < Array
|
5
|
+
def to_s
|
6
|
+
join('/')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Core
|
11
|
+
attr_accessor :line, :file
|
12
|
+
|
13
|
+
MAPPING_RECIPES = {
|
14
|
+
:github => {
|
15
|
+
:top => 'https://{host}/{path}',
|
16
|
+
:ref => 'https://{host}/{path}/tree/{short_ref}',
|
17
|
+
:rev => 'https://{host}/{path}/commit/{commit}',
|
18
|
+
:file => 'https://{host}/{path}/blob/{short_rev}/{file}{line && "#L%d" % line}'
|
19
|
+
},
|
20
|
+
|
21
|
+
:gitweb => {
|
22
|
+
:top => 'http://{host}/?p={path[-2..-1]}.git',
|
23
|
+
:ref => 'http://{host}/?p={path[-2..-1]}.git;h={ref}',
|
24
|
+
:rev => 'http://{host}/?p={path[-2..-1]}.git;a=commit;h={ref}',
|
25
|
+
# XXX
|
26
|
+
# I don't know file url of gitweb...
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
def template_type
|
31
|
+
if @file
|
32
|
+
:file
|
33
|
+
else
|
34
|
+
mode
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def init!(host, name)
|
39
|
+
mapping = MAPPING_RECIPES[name] or abort "Recipe '#{name}' not found"
|
40
|
+
mapping.each do |mode,template|
|
41
|
+
system %Q(git config --global browse-remote.#{host}.#{mode} '#{template}')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def url
|
46
|
+
if target && !@file && File.exists?(target)
|
47
|
+
self.target, @file = nil, target
|
48
|
+
end
|
49
|
+
|
50
|
+
if target
|
51
|
+
if Git.is_valid_rev? target
|
52
|
+
@ref = Git.full_name_of_rev(target)
|
53
|
+
elsif Git.is_valid_remote? target
|
54
|
+
@remote, @ref = target, 'master'
|
55
|
+
else
|
56
|
+
abort "Not a valid ref or remote: #{target}"
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@ref = Git.symbolic_name_of_head
|
60
|
+
end
|
61
|
+
|
62
|
+
if @ref == 'HEAD'
|
63
|
+
@ref = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
remote_url = `git config remote.#{remote}.url`[/.+/] or
|
67
|
+
abort "Could not get remote url: #{remote}"
|
68
|
+
|
69
|
+
host, *path = remote_url.sub(%r(^\w+://), '').sub(/^[\w-]+@/, '').split(/[\/:]+/)
|
70
|
+
path.last.sub!(/\.git$/, '')
|
71
|
+
path = Path.new(path)
|
72
|
+
|
73
|
+
template = `git config --get browse-remote.#{host}.#{template_type}`[/.+/]
|
74
|
+
if not template and host == 'github.com'
|
75
|
+
template = MAPPING_RECIPES[:github][template_type.to_sym] or
|
76
|
+
abort "No '#{template_type}' mapping found for #{host} (maybe `git browse-remote --init` required)"
|
77
|
+
end
|
78
|
+
|
79
|
+
url = template.gsub(/\{(.+?)\}/) { |m| eval($1) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def remote=(remote)
|
83
|
+
@remote = remote
|
84
|
+
end
|
85
|
+
|
86
|
+
def remote
|
87
|
+
return @remote if @remote
|
88
|
+
|
89
|
+
if ref
|
90
|
+
if ref.match(%r<^(?:refs/)?remotes/([^/]+)/>)
|
91
|
+
@remote = $1
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
@remote ||= 'origin'
|
96
|
+
end
|
97
|
+
|
98
|
+
def mode=(mode)
|
99
|
+
@mode = mode
|
100
|
+
end
|
101
|
+
|
102
|
+
def mode
|
103
|
+
return @mode if @mode
|
104
|
+
|
105
|
+
if ref
|
106
|
+
if ref.match(%r<^((?:refs/)?(?:heads|remotes/[^/]+)/)?master$>)
|
107
|
+
@mode = :top
|
108
|
+
elsif ref.match(%r<^(?:refs/)?(?:heads|tags|remotes)/>)
|
109
|
+
@mode = :ref
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
@mode || :rev
|
114
|
+
end
|
115
|
+
|
116
|
+
def _commit(short = false)
|
117
|
+
if short
|
118
|
+
Git.parse_rev_short(target || 'HEAD')
|
119
|
+
else
|
120
|
+
Git.parse_rev(target || 'HEAD')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def commit
|
125
|
+
_commit
|
126
|
+
end
|
127
|
+
|
128
|
+
def short_commit
|
129
|
+
_commit(true)
|
130
|
+
end
|
131
|
+
|
132
|
+
def _rev(short = false)
|
133
|
+
if mode == :rev
|
134
|
+
_commit(short)
|
135
|
+
else
|
136
|
+
_ref(short) || _commit(short)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def rev
|
141
|
+
_rev
|
142
|
+
end
|
143
|
+
|
144
|
+
def short_rev
|
145
|
+
_rev(true)
|
146
|
+
end
|
147
|
+
|
148
|
+
def _ref(short = false)
|
149
|
+
if short
|
150
|
+
@ref.sub(%r(^refs/), '').
|
151
|
+
sub(%r(^heads/), '').
|
152
|
+
sub(%r(^tags/), '').
|
153
|
+
sub(%r(^remotes/([^/]+)/), '')
|
154
|
+
else
|
155
|
+
@ref
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def ref
|
160
|
+
_ref
|
161
|
+
end
|
162
|
+
|
163
|
+
def short_ref
|
164
|
+
_ref(true)
|
165
|
+
end
|
166
|
+
|
167
|
+
def target=(target)
|
168
|
+
@target = target
|
169
|
+
end
|
170
|
+
|
171
|
+
def target
|
172
|
+
return @target if @target
|
173
|
+
@target ||= Git.resolved_head
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Git::Browse::Remote
|
2
|
+
module Git
|
3
|
+
def self.is_valid_rev?(target)
|
4
|
+
`git rev-parse --verify --quiet #{target}` && $? == 0
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.is_valid_remote?(remote)
|
8
|
+
`git config --get remote.#{remote}.url`.chomp.empty? == false
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse_rev(ref)
|
12
|
+
`git rev-parse #{ref}`.chomp
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parse_rev_short(ref)
|
16
|
+
`git rev-parse --short #{ref}`.chomp
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.full_name_of_rev(rev)
|
20
|
+
`git rev-parse --symbolic-full-name #{rev}`[/.+/] or `git rev-parse --symbolic-full-name #{name_rev(rev)}`[/.+/]
|
21
|
+
end
|
22
|
+
|
23
|
+
# the ref whom HEAD points to
|
24
|
+
def self.resolved_head
|
25
|
+
`git symbolic-ref -q HEAD`[/.+/]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.name_rev(rev)
|
29
|
+
`git name-rev --name-only #{rev}`.chomp
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.symbolic_name_of_head
|
33
|
+
name_rev('HEAD').sub(%r(\^0$), '') # some workaround for ^0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'git/browse/remote/core'
|
2
|
+
require 'git/browse/remote/version'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
module Git::Browse::Remote
|
6
|
+
class Runner
|
7
|
+
def initialize(args)
|
8
|
+
@args = args
|
9
|
+
@core = Core.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
OptionParser.new do |opt|
|
14
|
+
opt.banner = 'git browse-remote [options] [<commit> | <remote>] [--] [<file>]'
|
15
|
+
opt.version = VERSION
|
16
|
+
opt.on('-r', '--remote=<remote>', 'specify remote') { |r| @core.remote = r }
|
17
|
+
|
18
|
+
opt.on('--stdout', 'prints URL instead of opening browser') { @stdout = true }
|
19
|
+
|
20
|
+
opt.on('--top', 'open `top` page') { @core.mode = :top }
|
21
|
+
opt.on('--rev', 'open `rev` page') { @core.mode = :rev }
|
22
|
+
opt.on('--ref', 'open `ref` page') { @core.mode = :ref }
|
23
|
+
opt.on('--init [<host>=<recipe>]', 'initialize default url mappings') do |config|
|
24
|
+
if config
|
25
|
+
host, name = *config.split(/=/, 2)
|
26
|
+
else
|
27
|
+
host, name = 'github.com', 'github'
|
28
|
+
end
|
29
|
+
|
30
|
+
STDERR.puts "Writing config for #{host}..."
|
31
|
+
|
32
|
+
@core.init!(host, name.to_sym)
|
33
|
+
|
34
|
+
STDERR.puts 'Mappings generated:'
|
35
|
+
exec "git config --get-regexp ^browse-remote\\.#{host}\\."
|
36
|
+
end
|
37
|
+
opt.on('-L <n>', 'specify line number (only meaningful on file mode)', Integer) { |n| @core.line = n }
|
38
|
+
end.parse!(@args)
|
39
|
+
|
40
|
+
@core.target, @core.file = *@args[0..1]
|
41
|
+
|
42
|
+
if @stdout
|
43
|
+
puts @core.url
|
44
|
+
else
|
45
|
+
exec 'git', 'web--browse', @core.url
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/bin_spec.rb
ADDED
@@ -0,0 +1,333 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'pathname'
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
unless ENV['CI']
|
7
|
+
require 'simplecov'
|
8
|
+
|
9
|
+
module SimpleCov
|
10
|
+
def self.lap
|
11
|
+
if running
|
12
|
+
@result = SimpleCov::Result.new(Coverage.result.merge_resultset(SimpleCov::ResultMerger.merged_result.original_result))
|
13
|
+
SimpleCov::ResultMerger.store_result(@result)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
ROOT = Pathname.new(__FILE__).parent.parent
|
20
|
+
|
21
|
+
$:.unshift ROOT.join('lib').to_s
|
22
|
+
|
23
|
+
require 'git/browse/remote'
|
24
|
+
|
25
|
+
def git(*args)
|
26
|
+
if Open3.methods(false).include? :capture3
|
27
|
+
out, err, status = Open3.capture3('git', *args.map { |arg| arg.to_s })
|
28
|
+
else
|
29
|
+
out = `git #{args.map { |arg| arg.to_s.shellescape }.join(' ')}`
|
30
|
+
status = $?.to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
if status != 0
|
34
|
+
abort "git #{args.join(' ')} failed: #{err}"
|
35
|
+
end
|
36
|
+
|
37
|
+
out[/.*/]
|
38
|
+
end
|
39
|
+
|
40
|
+
RSpec.configure do |config|
|
41
|
+
config.before(:all) do
|
42
|
+
@pwd = Dir.pwd
|
43
|
+
@tmpdir = Dir.mktmpdir
|
44
|
+
Dir.chdir @tmpdir
|
45
|
+
|
46
|
+
@sha1 = {}
|
47
|
+
|
48
|
+
git :init
|
49
|
+
|
50
|
+
git :config, '--local', 'user.email', 'gbr@example.com'
|
51
|
+
git :config, '--local', 'user.name', 'git-browse-remote tester'
|
52
|
+
|
53
|
+
git :remote, 'add', 'origin', 'https://github.com/user/repo.git'
|
54
|
+
git :remote, 'add', 'origin2', 'git@gh-mirror.host:user/repo2'
|
55
|
+
|
56
|
+
FileUtils.copy_file ROOT + 'README.md', 'README.md'
|
57
|
+
git :add, 'README.md'
|
58
|
+
git :commit, '-m' '1st commit'
|
59
|
+
|
60
|
+
git :commit, '-m' '2nd commit', '--allow-empty'
|
61
|
+
|
62
|
+
git :checkout, '-b', 'branch-1'
|
63
|
+
|
64
|
+
git :commit, '-m' 'branched commit', '--allow-empty'
|
65
|
+
@sha1[:'branch-1'] = git 'rev-parse', 'HEAD'
|
66
|
+
|
67
|
+
git :checkout, 'master'
|
68
|
+
|
69
|
+
git :commit, '-m' '3rd commit (tagged)', '--allow-empty'
|
70
|
+
git :tag, 'tag-a'
|
71
|
+
|
72
|
+
git :commit, '-m' '4th commit (remote HEAD)', '--allow-empty'
|
73
|
+
git :remote, 'add', 'local-remote', '.git'
|
74
|
+
git :remote, 'update', 'local-remote'
|
75
|
+
git :remote, 'set-url', 'local-remote', 'https://github.com/user/repo3.git'
|
76
|
+
|
77
|
+
git :commit, '-m' '5th commit', '--allow-empty'
|
78
|
+
@sha1[:'master~1'] = git 'rev-parse', 'HEAD'
|
79
|
+
|
80
|
+
git :commit, '-m' '6th commit', '--allow-empty'
|
81
|
+
@sha1[:master] = git 'rev-parse', 'HEAD'
|
82
|
+
|
83
|
+
# system 'git log --abbrev-commit --oneline --decorate --graph --all'
|
84
|
+
# the commit graph looks like below;
|
85
|
+
#
|
86
|
+
# * e6b5d6f (local-remote/branch-1, branch-1) branched commit
|
87
|
+
# | * 03b1d4d (HEAD, master) 6th commit
|
88
|
+
# | * b591899 5th commit
|
89
|
+
# | * 3139e94 (local-remote/master) 4th commit (remote HEAD)
|
90
|
+
# | * a423770 (tag: tag-a) 3rd commit (tagged)
|
91
|
+
# |/
|
92
|
+
# * 06f6ebb 2nd commit
|
93
|
+
# * ff7b92b 1st commit
|
94
|
+
end
|
95
|
+
|
96
|
+
config.after(:all) do
|
97
|
+
FileUtils.remove_entry @tmpdir
|
98
|
+
Dir.chdir @pwd
|
99
|
+
end
|
100
|
+
|
101
|
+
config.after(:each) do
|
102
|
+
git :checkout, 'master'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
module Kernel
|
107
|
+
def exec(*args)
|
108
|
+
$exec_args = args
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def git_browse_remote(args)
|
113
|
+
begin
|
114
|
+
SimpleCov.start unless ENV['CI']
|
115
|
+
ARGV.replace(args)
|
116
|
+
load ROOT + 'bin/git-browse-remote', true
|
117
|
+
true
|
118
|
+
rescue
|
119
|
+
false
|
120
|
+
ensure
|
121
|
+
SimpleCov.lap unless ENV['CI']
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def opened_url
|
126
|
+
git_browse_remote(args)
|
127
|
+
|
128
|
+
if $exec_args[0..1] == [ 'git', 'web--browse' ]
|
129
|
+
$exec_args[2]
|
130
|
+
else
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def when_run_with_args(*args, &block)
|
136
|
+
context "when run with args #{args}" do
|
137
|
+
let(:args) { args }
|
138
|
+
instance_eval(&block)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'git-browse-remote' do
|
143
|
+
when_run_with_args '--init', 'gh-mirror.host=github' do
|
144
|
+
it 'should run successfully' do
|
145
|
+
expect(git_browse_remote(args)).to be(true)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when on master' do
|
150
|
+
when_run_with_args do
|
151
|
+
it 'should open top page' do
|
152
|
+
expect(opened_url).to eq("https://github.com/user/repo")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
when_run_with_args '--top' do
|
157
|
+
it 'should open top page' do
|
158
|
+
expect(opened_url).to eq("https://github.com/user/repo")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
when_run_with_args '--rev' do
|
163
|
+
it 'should open rev page' do
|
164
|
+
expect(opened_url).to eq("https://github.com/user/repo/commit/#{@sha1[:master]}")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
when_run_with_args '--ref' do
|
169
|
+
it 'should open ref page' do
|
170
|
+
expect(opened_url).to eq("https://github.com/user/repo/tree/master")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
when_run_with_args 'HEAD~1' do
|
175
|
+
it 'should open previous rev\'s page' do
|
176
|
+
expect(opened_url).to eq("https://github.com/user/repo/commit/#{@sha1[:'master~1']}")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
when_run_with_args 'master' do
|
181
|
+
it 'should open top page' do
|
182
|
+
expect(opened_url).to eq("https://github.com/user/repo")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
when_run_with_args '--', 'README.md' do
|
187
|
+
it 'should open the file page' do
|
188
|
+
expect(opened_url).to eq("https://github.com/user/repo/blob/master/README.md")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
when_run_with_args '--rev', '--', 'README.md' do
|
193
|
+
it 'should open the file page by revision' do
|
194
|
+
expect(opened_url).to eq("https://github.com/user/repo/blob/#{@sha1[:master][0..6]}/README.md")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
when_run_with_args '-L3', '--', 'README.md' do
|
199
|
+
it 'should open the file at the specified line' do
|
200
|
+
expect(opened_url).to eq("https://github.com/user/repo/blob/master/README.md#L3")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
when_run_with_args 'branch-1' do
|
205
|
+
it 'should open the branch page' do
|
206
|
+
expect(opened_url).to eq("https://github.com/user/repo/tree/branch-1")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
when_run_with_args '--rev', 'branch-1' do
|
211
|
+
it 'should open the rev page of the branch' do
|
212
|
+
expect(opened_url).to eq("https://github.com/user/repo/commit/#{@sha1[:'branch-1']}")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
when_run_with_args '--remote', 'origin2' do
|
217
|
+
it 'should open the specified remote page' do
|
218
|
+
expect(opened_url).to eq("https://gh-mirror.host/user/repo2")
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
when_run_with_args '-r', 'origin2' do
|
223
|
+
it 'should open the specified remote page' do
|
224
|
+
expect(opened_url).to eq("https://gh-mirror.host/user/repo2")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
when_run_with_args '-r', 'origin2', '--rev' do
|
229
|
+
it 'should open the specified remote page and the revision' do
|
230
|
+
expect(opened_url).to eq("https://gh-mirror.host/user/repo2/commit/#{@sha1[:master]}")
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
when_run_with_args 'README.md' do
|
235
|
+
it 'should open file file page' do
|
236
|
+
expect(opened_url).to eq("https://github.com/user/repo/blob/master/README.md")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
when_run_with_args 'origin2' do
|
241
|
+
it 'should open the remote' do
|
242
|
+
expect(opened_url).to eq("https://gh-mirror.host/user/repo2")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context 'on some branch' do
|
248
|
+
before { git :checkout, 'branch-1' }
|
249
|
+
|
250
|
+
when_run_with_args do
|
251
|
+
it 'should open the current branch page' do
|
252
|
+
expect(opened_url).to eq("https://github.com/user/repo/tree/branch-1")
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
when_run_with_args '--top' do
|
257
|
+
it 'should open the top page' do
|
258
|
+
expect(opened_url).to eq("https://github.com/user/repo")
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
when_run_with_args '--rev' do
|
263
|
+
it 'should open the revision page of current HEAD' do
|
264
|
+
expect(opened_url).to eq("https://github.com/user/repo/commit/#{@sha1[:'branch-1']}")
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
when_run_with_args 'README.md' do
|
269
|
+
it 'should open the file page at current branch' do
|
270
|
+
expect(opened_url).to eq("https://github.com/user/repo/blob/branch-1/README.md")
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
context 'on detached HEAD' do
|
276
|
+
before { git :checkout, 'HEAD~1' }
|
277
|
+
|
278
|
+
when_run_with_args do
|
279
|
+
it 'should open the revision page' do
|
280
|
+
expect(opened_url).to eq("https://github.com/user/repo/commit/#{@sha1[:'master~1']}")
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
when_run_with_args 'HEAD' do
|
285
|
+
it 'should open the revision page' do
|
286
|
+
expect(opened_url).to eq("https://github.com/user/repo/commit/#{@sha1[:'master~1']}")
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
context 'on tag' do
|
292
|
+
before { git :checkout, 'tag-a' }
|
293
|
+
|
294
|
+
when_run_with_args do
|
295
|
+
it 'should open the tag page' do
|
296
|
+
expect(opened_url).to eq("https://github.com/user/repo/tree/tag-a")
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'on remote branch' do
|
302
|
+
before { git :checkout, 'local-remote/master' }
|
303
|
+
|
304
|
+
when_run_with_args do
|
305
|
+
it 'should open the remote' do
|
306
|
+
expect(opened_url).to eq("https://github.com/user/repo3")
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'after changing branches' do
|
312
|
+
before {
|
313
|
+
git :checkout, 'branch-1'
|
314
|
+
git :checkout, 'master'
|
315
|
+
}
|
316
|
+
|
317
|
+
when_run_with_args 'HEAD@{1}' do
|
318
|
+
it 'should open the previous branch page' do
|
319
|
+
expect(opened_url).to eq("https://github.com/user/repo/tree/branch-1")
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
when_run_with_args '--ref', 'HEAD@{1}' do
|
324
|
+
it 'should open the previous branch page' do
|
325
|
+
expect(opened_url).to eq("https://github.com/user/repo/tree/branch-1")
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'should abort on invalid ref' do
|
331
|
+
expect { git_browse_remote([ 'xxx-nonexistent-ref' ]) }.to raise_error SystemExit
|
332
|
+
end
|
333
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'git/browse/remote/core'
|
2
|
+
|
3
|
+
describe Git::Browse::Remote::Core do
|
4
|
+
subject(:core) { Git::Browse::Remote::Core.new }
|
5
|
+
|
6
|
+
describe '#template_type' do
|
7
|
+
context 'if @file set' do
|
8
|
+
before { core.file = 'README.md' }
|
9
|
+
|
10
|
+
it 'is :file' do
|
11
|
+
expect(core.template_type).to be(:file)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'if @file not set' do
|
16
|
+
it 'is same as #mode' do
|
17
|
+
expect(core.template_type).to be(core.mode)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#remote' do
|
23
|
+
context 'by default' do
|
24
|
+
it 'is "origin"' do
|
25
|
+
expect(core.remote).to eq('origin')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'if remote set' do
|
30
|
+
before { core.remote = 'remote-foo' }
|
31
|
+
|
32
|
+
it 'is the set value' do
|
33
|
+
expect(core.remote).to eq('remote-foo')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'if #ref is a remote ref' do
|
38
|
+
it 'is the remote name in the ref' do
|
39
|
+
core.stub(:ref).and_return('remotes/remote-bar/master')
|
40
|
+
expect(core.remote).to eq('remote-bar')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#mode' do
|
46
|
+
context 'by default' do
|
47
|
+
it 'is :rev' do
|
48
|
+
expect(core.mode).to eq(:rev)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'if mode set' do
|
53
|
+
before { core.mode = :foo }
|
54
|
+
|
55
|
+
it 'is the set value' do
|
56
|
+
expect(core.mode).to eq(:foo)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'if #ref points to master' do
|
61
|
+
it 'is :top' do
|
62
|
+
core.stub(:ref).and_return('refs/heads/master')
|
63
|
+
expect(core.mode).to eq(:top)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'if #ref points to some ref' do
|
68
|
+
it 'is :ref' do
|
69
|
+
core.stub(:ref).and_return('refs/heads/branch-a')
|
70
|
+
expect(core.mode).to eq(:ref)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#commit' do
|
76
|
+
it 'calls Git.parse_rev with #target' do
|
77
|
+
Git::Browse::Remote::Git.should_receive(:parse_rev).with('__TARGET__').and_return('0000000000000000000000000000000000000000')
|
78
|
+
core.stub(:target).and_return('__TARGET__')
|
79
|
+
expect(core.commit).to eq('0000000000000000000000000000000000000000')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#short_commit' do
|
84
|
+
it 'calls Git.parse_rev_short with #target' do
|
85
|
+
Git::Browse::Remote::Git.should_receive(:parse_rev_short).with('__TARGET__').and_return('00000000')
|
86
|
+
core.stub(:target).and_return('__TARGET__')
|
87
|
+
expect(core.short_commit).to eq('00000000')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#_rev' do
|
92
|
+
context 'if #mode is :ref (not :rev)' do
|
93
|
+
before { core.stub(:mode).and_return(:ref) }
|
94
|
+
|
95
|
+
context 'and #_ref is not defined' do
|
96
|
+
it 'returns the #_commit value' do
|
97
|
+
core.should_receive(:_commit).and_return('0000000000000000000000000000000000000000')
|
98
|
+
expect(core._rev).to eq('0000000000000000000000000000000000000000')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'and #_ref is defined' do
|
103
|
+
it 'returns the #_ref value' do
|
104
|
+
core.should_receive(:_ref).and_return('a-ref')
|
105
|
+
expect(core._rev).to eq('a-ref')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'if #mode is :rev' do
|
111
|
+
before { core.stub(:mode).and_return(:rev) }
|
112
|
+
|
113
|
+
context 'and #_ref is not defined' do
|
114
|
+
it 'returns the #_commit value' do
|
115
|
+
core.should_receive(:_commit).and_return('0000000000000000000000000000000000000000')
|
116
|
+
expect(core._rev).to eq('0000000000000000000000000000000000000000')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'and #_ref is defined' do
|
121
|
+
it 'returns the #_commit value though' do
|
122
|
+
core.stub(:_ref).and_return('a-ref')
|
123
|
+
core.should_receive(:_commit).and_return('0000000000000000000000000000000000000000')
|
124
|
+
expect(core._rev).to eq('0000000000000000000000000000000000000000')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#short_ref' do
|
131
|
+
context 'if @ref is "refs/heads/master"' do
|
132
|
+
before { core.instance_variable_set :@ref, 'refs/heads/master' }
|
133
|
+
it 'should be "master"' do
|
134
|
+
expect(core.short_ref).to eq('master')
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'if @ref is "refs/heads/fix/some/bug"' do
|
139
|
+
before { core.instance_variable_set :@ref, 'refs/heads/fix/some/bug' }
|
140
|
+
it 'should be "fix/some/bug"' do
|
141
|
+
expect(core.short_ref).to eq('fix/some/bug')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'if @ref is "refs/tags/v0.0.1"' do
|
146
|
+
before { core.instance_variable_set :@ref, 'refs/tags/v0.0.1' }
|
147
|
+
it 'should be "v0.0.1"' do
|
148
|
+
expect(core.short_ref).to eq('v0.0.1')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'if @ref is "refs/remotes/origin/foo/bar"' do
|
153
|
+
before { core.instance_variable_set :@ref, 'refs/remotes/origin/foo/bar' }
|
154
|
+
it 'should be "foo/bar"' do
|
155
|
+
expect(core.short_ref).to eq('foo/bar')
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
metadata
CHANGED
@@ -1,47 +1,162 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-browse-remote
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- motemen
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
11
|
+
date: 2013-10-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.7.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: terminal-notifier-guard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
14
111
|
description:
|
15
|
-
email:
|
112
|
+
email:
|
113
|
+
- motemen@gmail.com
|
16
114
|
executables:
|
17
115
|
- git-browse-remote
|
18
116
|
extensions: []
|
19
117
|
extra_rdoc_files: []
|
20
118
|
files:
|
119
|
+
- .gitignore
|
120
|
+
- .travis.yml
|
121
|
+
- Gemfile
|
122
|
+
- Guardfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
21
126
|
- bin/git-browse-remote
|
127
|
+
- git-browse-remote.gemspec
|
128
|
+
- lib/git/browse/remote.rb
|
129
|
+
- lib/git/browse/remote/core.rb
|
130
|
+
- lib/git/browse/remote/git.rb
|
131
|
+
- lib/git/browse/remote/runner.rb
|
132
|
+
- lib/git/browse/remote/version.rb
|
133
|
+
- spec/bin_spec.rb
|
134
|
+
- spec/lib/git/browse/remote/core_spec.rb
|
22
135
|
homepage: https://github.com/motemen/git-browse-remote
|
23
|
-
licenses:
|
136
|
+
licenses:
|
137
|
+
- MIT
|
138
|
+
metadata: {}
|
24
139
|
post_install_message:
|
25
140
|
rdoc_options: []
|
26
141
|
require_paths:
|
27
142
|
- lib
|
28
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
-
none: false
|
30
144
|
requirements:
|
31
|
-
- -
|
145
|
+
- - '>='
|
32
146
|
- !ruby/object:Gem::Version
|
33
147
|
version: '0'
|
34
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
149
|
requirements:
|
37
|
-
- -
|
150
|
+
- - '>='
|
38
151
|
- !ruby/object:Gem::Version
|
39
152
|
version: '0'
|
40
153
|
requirements: []
|
41
154
|
rubyforge_project:
|
42
|
-
rubygems_version:
|
155
|
+
rubygems_version: 2.0.3
|
43
156
|
signing_key:
|
44
|
-
specification_version:
|
157
|
+
specification_version: 4
|
45
158
|
summary: Open web browser to view remote Git repositories
|
46
|
-
test_files:
|
159
|
+
test_files:
|
160
|
+
- spec/bin_spec.rb
|
161
|
+
- spec/lib/git/browse/remote/core_spec.rb
|
47
162
|
has_rdoc:
|