git-browse-remote 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/motemen/git-browse-remote.png?branch=master)](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:
|