twig 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/CONTRIBUTING.md +26 -0
- data/Gemfile +2 -0
- data/HISTORY.md +6 -0
- data/LICENSE.md +22 -0
- data/README.md +232 -0
- data/Rakefile +10 -0
- data/bin/twig +10 -0
- data/bin/twig-gh-open +41 -0
- data/bin/twig-gh-update +93 -0
- data/bin/twig-help +4 -0
- data/install +18 -0
- data/lib/twig/branch.rb +72 -0
- data/lib/twig/cli.rb +177 -0
- data/lib/twig/commit_time.rb +32 -0
- data/lib/twig/display.rb +116 -0
- data/lib/twig/options.rb +55 -0
- data/lib/twig/util.rb +9 -0
- data/lib/twig/version.rb +3 -0
- data/lib/twig.rb +119 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/twig/branch_spec.rb +232 -0
- data/spec/twig/cli_spec.rb +291 -0
- data/spec/twig/commit_time_spec.rb +47 -0
- data/spec/twig/display_spec.rb +117 -0
- data/spec/twig/options_spec.rb +126 -0
- data/spec/twig/util_spec.rb +16 -0
- data/spec/twig_spec.rb +220 -0
- data/twig.gemspec +38 -0
- metadata +166 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-1.8.7-p358@twig --create
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
How to contribute
|
2
|
+
=================
|
3
|
+
|
4
|
+
Let's make life easier for people with lots of Git branches.
|
5
|
+
|
6
|
+
Found a bug or have a suggestion? [Please open an issue][issues] or ping
|
7
|
+
[@ronalddevera on Twitter][twitter].
|
8
|
+
|
9
|
+
If you want to hack on some code, even better! Here are the basics:
|
10
|
+
|
11
|
+
1. Fork the Twig repo.
|
12
|
+
2. Check out the [**`development`** branch][dev branch]; the `master` branch is
|
13
|
+
for stable builds only.
|
14
|
+
3. Run the tests to make sure that they pass on your machine: `bundle && rake`
|
15
|
+
4. Add one or more failing tests for your feature or bug fix.
|
16
|
+
5. Write your feature or bug fix to make the test(s) pass.
|
17
|
+
6. Test the change manually:
|
18
|
+
1. `gem build twig.gemspec`
|
19
|
+
2. `gem install twig-x.y.z.gem` (fill in the current version number)
|
20
|
+
7. Push to your fork and submit a pull request.
|
21
|
+
|
22
|
+
Thanks for contributing!
|
23
|
+
|
24
|
+
[issues]: https://github.com/rondevera/twig/issues
|
25
|
+
[twitter]: https://twitter.com/ronalddevera
|
26
|
+
[dev branch]: https://github.com/rondevera/twig/commits/development
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ron DeVera
|
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,232 @@
|
|
1
|
+
Twig: Your personal Git branch assistant.
|
2
|
+
=========================================
|
3
|
+
|
4
|
+
It's hard enough trying to remember the names of all of your Git branches. You
|
5
|
+
also need those branches' issue tracker ids, issue statuses, and reminders of
|
6
|
+
what to do next with each branch. `git branch` only lists them in alphabetical
|
7
|
+
order, which just doesn't cut it.
|
8
|
+
|
9
|
+
**Twig shows you your most recent branches, and remembers branch details for
|
10
|
+
you.** It supports subcommands, like automatically fetching statuses from your
|
11
|
+
issue tracking system. It's flexible enough to fit your everyday Git workflow,
|
12
|
+
and will save you a ton of time.
|
13
|
+
|
14
|
+
Here's how Twig looks in action:
|
15
|
+
|
16
|
+
$ twig
|
17
|
+
|
18
|
+
issue status todo branch
|
19
|
+
----- ------ ---- ------
|
20
|
+
2013-01-26 18:00:21 (7m ago) 486 In progress Rebase optimize-all-the-things
|
21
|
+
2013-01-26 16:49:21 (2h ago) 268 In progress - whitespace-all-the-things
|
22
|
+
2013-01-23 18:35:21 (3d ago) 159 Shipped Test in prod * refactor-all-the-things
|
23
|
+
2013-01-22 17:12:09 (4d ago) - - - development
|
24
|
+
2013-01-20 19:45:42 (6d ago) - - - master
|
25
|
+
|
26
|
+
|
27
|
+
Installation
|
28
|
+
============
|
29
|
+
|
30
|
+
gem install twig
|
31
|
+
|
32
|
+
|
33
|
+
Usage
|
34
|
+
=====
|
35
|
+
|
36
|
+
Twig lets you get/set custom properties for each branch, and list branches
|
37
|
+
chronologically with their properties.
|
38
|
+
|
39
|
+
* `twig`: List all branches with properties, newest first
|
40
|
+
* `twig <property>`: Get a property for the current branch
|
41
|
+
* `twig <property> <value>`: Set a property for the current branch
|
42
|
+
* `twig --unset <property>`: Unset a property for the current branch
|
43
|
+
* `twig <property> -b <branch>`: Get property for any branch
|
44
|
+
* `twig <property> <value> -b <branch>`: Set property for any branch
|
45
|
+
* `twig --unset <property> -b <branch>`: Unset property for any branch
|
46
|
+
* `twig --help`: More info
|
47
|
+
|
48
|
+
|
49
|
+
Filtering branches
|
50
|
+
------------------
|
51
|
+
|
52
|
+
Twig lists all of your branches by default (newest first), but you can filter
|
53
|
+
them by name and age:
|
54
|
+
|
55
|
+
* `twig --only-branch <pattern>`:
|
56
|
+
Only list branches whose name matches a given pattern
|
57
|
+
* `twig --except-branch <pattern>`:
|
58
|
+
Don't list branches whose name matches a given pattern
|
59
|
+
* `twig --max-days-old <age>`:
|
60
|
+
Only list branches below a given age
|
61
|
+
* `twig --all`:
|
62
|
+
List all branches regardless of other filtering options
|
63
|
+
|
64
|
+
You can put your most frequently used options into `~/.twigrc`, and they'll be
|
65
|
+
automatically included when you run `twig`. Example:
|
66
|
+
|
67
|
+
# ~/.twigrc:
|
68
|
+
except-branch: staging
|
69
|
+
max-days-old: 30
|
70
|
+
|
71
|
+
|
72
|
+
Examples
|
73
|
+
--------
|
74
|
+
|
75
|
+
List your branches, and highlight the current branch:
|
76
|
+
|
77
|
+
$ twig
|
78
|
+
|
79
|
+
2013-01-26 18:07:21 (7m ago) * refactor-all-the-things
|
80
|
+
2013-01-24 17:12:09 (2d ago) development
|
81
|
+
2013-01-23 19:45:42 (3d ago) master
|
82
|
+
|
83
|
+
Remember a branch's issue tracker id:
|
84
|
+
|
85
|
+
$ git checkout my-branch
|
86
|
+
Switched to branch 'my-branch'.
|
87
|
+
|
88
|
+
$ twig issue 123
|
89
|
+
Saved property "issue" as "123" for branch "my-branch".
|
90
|
+
# Nearly any property name will do, like "bug" or "ticket".
|
91
|
+
|
92
|
+
$ twig issue
|
93
|
+
123
|
94
|
+
|
95
|
+
$ open "https://github.com/myname/myproject/issues/`twig issue`"
|
96
|
+
# Opens a browser window for this GitHub issue (in OS X).
|
97
|
+
|
98
|
+
Keep notes on what you need to do with each branch:
|
99
|
+
|
100
|
+
$ twig todo "Run tests"
|
101
|
+
Saved property "todo" as "Run tests" for branch "my-branch".
|
102
|
+
|
103
|
+
$ twig todo "Deploy" -b finished-branch
|
104
|
+
Saved property "todo" as "Deploy" for branch "finished-branch".
|
105
|
+
|
106
|
+
$ twig
|
107
|
+
|
108
|
+
todo branch
|
109
|
+
---- ------
|
110
|
+
2013-01-26 18:00:25 (7m ago) Run tests * my-branch
|
111
|
+
2013-01-23 18:35:12 (3d ago) Deploy finished-branch
|
112
|
+
2013-01-22 17:12:23 (4d ago) - master
|
113
|
+
|
114
|
+
Remember the order in which you were rebasing your stack of branches:
|
115
|
+
|
116
|
+
$ git checkout master
|
117
|
+
Switched to branch 'master'.
|
118
|
+
|
119
|
+
$ twig rebase-onto branch2 -b branch3
|
120
|
+
Saved property "rebase-onto" as "branch2" for branch "branch3".
|
121
|
+
|
122
|
+
$ twig rebase-onto branch1 -b branch2
|
123
|
+
Saved property "rebase-onto" as "branch1" for branch "branch2".
|
124
|
+
|
125
|
+
$ twig
|
126
|
+
|
127
|
+
rebase-onto branch
|
128
|
+
----------- ------
|
129
|
+
2013-01-26 18:00:25 (7m ago) branch2 branch3
|
130
|
+
2013-01-26 16:49:47 (2h ago) branch1 branch2
|
131
|
+
2013-01-23 18:35:12 (3d ago) - branch1
|
132
|
+
2013-01-22 17:12:23 (4d ago) - * master
|
133
|
+
|
134
|
+
You can set just about any custom property you need to remember for each branch.
|
135
|
+
|
136
|
+
|
137
|
+
Subcommands
|
138
|
+
===========
|
139
|
+
|
140
|
+
Twig comes with two subcommands, `gh-open` and `gh-update`, which are handy for
|
141
|
+
use with GitHub repositories.
|
142
|
+
|
143
|
+
While inside a Git repo, run `twig gh-open` to see the repo's GitHub URL, and open
|
144
|
+
a browser window if possible:
|
145
|
+
|
146
|
+
$ cd myproject
|
147
|
+
|
148
|
+
$ twig gh-open
|
149
|
+
GitHub URL: https://github.com/myname/myproject
|
150
|
+
# Also opens a browser window (OS X only).
|
151
|
+
|
152
|
+
If you're working on an issue for a GitHub repository, you can also use the
|
153
|
+
`gh-update` subcommand:
|
154
|
+
|
155
|
+
$ git checkout add-feature
|
156
|
+
Switched to branch 'add-feature'.
|
157
|
+
|
158
|
+
$ twig issue 222
|
159
|
+
Saved property "issue" as "222" for branch "add-feature".
|
160
|
+
|
161
|
+
$ twig
|
162
|
+
|
163
|
+
issue status branch
|
164
|
+
----- ------ ------
|
165
|
+
2013-01-26 18:00:25 (7m ago) 222 - * add-feature
|
166
|
+
2013-01-23 18:35:12 (3d ago) 111 - fix-bug
|
167
|
+
2013-01-22 17:12:23 (4d ago) - - master
|
168
|
+
|
169
|
+
$ twig gh-update
|
170
|
+
# Automatically looks up the GitHub issue status for each
|
171
|
+
# of your local branches, and saves it locally.
|
172
|
+
|
173
|
+
$ twig
|
174
|
+
|
175
|
+
issue status branch
|
176
|
+
----- ------ ------
|
177
|
+
2013-01-26 18:00:25 (7m ago) 222 open * add-feature
|
178
|
+
2013-01-23 18:35:12 (3d ago) 111 closed fix-bug
|
179
|
+
2013-01-22 17:12:23 (4d ago) - - master
|
180
|
+
|
181
|
+
Run `twig gh-update` periodically to keep up with GitHub issues locally.
|
182
|
+
|
183
|
+
You can write any Twig subcommand that fits your own Git workflow. To write a
|
184
|
+
Twig subcommand:
|
185
|
+
|
186
|
+
1. Write a script. Any language will do. (If you want to take advantage of
|
187
|
+
Twig's option parsing and branch processing, you'll need Ruby. See
|
188
|
+
[`bin/twig-gh-update`][twig-gh-update] for an example.)
|
189
|
+
2. Save it with the `twig-` prefix in your `$PATH`,
|
190
|
+
e.g., `~/bin/twig-my-subcommand`.
|
191
|
+
3. Make it executable: `chmod ugo+x ~/bin/twig-my-subcommand`
|
192
|
+
4. Run your subcommand: `twig my-subcommand` (with a *space* after `twig`)
|
193
|
+
|
194
|
+
[twig-gh-update]: https://github.com/rondevera/twig/blob/master/bin/twig-gh-update
|
195
|
+
|
196
|
+
Some ideas for subcommands:
|
197
|
+
|
198
|
+
* Get each branch's status for any issue tracking system that has an API,
|
199
|
+
like [JIRA](http://www.atlassian.com/software/jira/overview),
|
200
|
+
[FogBugz](http://www.fogcreek.com/fogbugz/), or
|
201
|
+
[Lighthouse](http://lighthouseapp.com/).
|
202
|
+
* Given an issue tracker id, check out that issue's branch locally. Great for
|
203
|
+
following teammates' branches, remembering their issue ids, and knowing when
|
204
|
+
they've shipped.
|
205
|
+
* Generate a formatted list of your branches from the past week. Useful for
|
206
|
+
emailing your team about what you're up to.
|
207
|
+
|
208
|
+
If you write a subcommand that others can appreciate, send a pull request or add
|
209
|
+
it to the [Twig wiki][wiki]!
|
210
|
+
|
211
|
+
|
212
|
+
More info
|
213
|
+
=========
|
214
|
+
|
215
|
+
- **Requirements:** Tested with Git 1.6.5 and Ruby 1.8.7. Probably works with
|
216
|
+
older software, but it's not guaranteed.
|
217
|
+
- **Contributing:** Found a bug or have a suggestion? [Please open an
|
218
|
+
issue][issues] or ping [@ronalddevera on Twitter][twitter]. If you want to
|
219
|
+
hack on some features or contribute a subcommand you've written, feel free to
|
220
|
+
fork and send a pull request for the **[development branch][dev branch]**.
|
221
|
+
(The master branch is for stable builds only.) See the full details in the
|
222
|
+
[Contributing][contributing] instructions.
|
223
|
+
- **History:** [History/changelog for Twig][history]
|
224
|
+
- **License:** Twig is released under the [MIT License][license].
|
225
|
+
|
226
|
+
[issues]: https://github.com/rondevera/twig/issues
|
227
|
+
[wiki]: https://github.com/rondevera/twig/wiki
|
228
|
+
[twitter]: https://twitter.com/ronalddevera
|
229
|
+
[dev branch]: https://github.com/rondevera/twig/commits/development
|
230
|
+
[contributing]: https://github.com/rondevera/twig/blob/master/CONTRIBUTING.md
|
231
|
+
[history]: https://github.com/rondevera/twig/blob/master/HISTORY.md
|
232
|
+
[license]: https://github.com/rondevera/twig/blob/master/LICENSE.md
|
data/Rakefile
ADDED
data/bin/twig
ADDED
data/bin/twig-gh-open
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Opens a browser window for the current GitHub repo.
|
4
|
+
#
|
5
|
+
# Author: Ron DeVera <http://rondevera.com>
|
6
|
+
|
7
|
+
class TwigGithubRepo
|
8
|
+
def initialize
|
9
|
+
if origin_url.empty? || username.empty? || repository.empty?
|
10
|
+
abort_for_non_github_repo
|
11
|
+
end
|
12
|
+
|
13
|
+
yield(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def origin_url
|
17
|
+
@origin_url ||= `git config remote.origin.url`.strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def origin_url_parts
|
21
|
+
@origin_url_parts ||= origin_url.split(/[\/:]/)
|
22
|
+
end
|
23
|
+
|
24
|
+
def username
|
25
|
+
@username ||= origin_url_parts[-2] || ''
|
26
|
+
end
|
27
|
+
|
28
|
+
def repository
|
29
|
+
@repo ||= origin_url_parts[-1].sub(/\.git$/, '') || ''
|
30
|
+
end
|
31
|
+
|
32
|
+
def abort_for_non_github_repo
|
33
|
+
abort 'This does not appear to be a GitHub repository.'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
TwigGithubRepo.new do |gh_repo|
|
38
|
+
url = "https://github.com/#{gh_repo.username}/#{gh_repo.repository}"
|
39
|
+
puts "GitHub URL: #{url}"
|
40
|
+
`which open && open #{url}`
|
41
|
+
end
|
data/bin/twig-gh-update
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Updates each branch with the latest issue status on GitHub.
|
4
|
+
#
|
5
|
+
# Author: Ron DeVera <http://rondevera.com>
|
6
|
+
|
7
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'twig')
|
8
|
+
require 'rubygems'
|
9
|
+
require 'json'
|
10
|
+
require 'net/https'
|
11
|
+
require 'uri'
|
12
|
+
|
13
|
+
class TwigGithubRepo
|
14
|
+
def initialize
|
15
|
+
if origin_url.empty? || username.empty? || repository.empty?
|
16
|
+
abort_for_non_github_repo
|
17
|
+
end
|
18
|
+
|
19
|
+
yield(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def origin_url
|
23
|
+
@origin_url ||= `git config remote.origin.url`.strip
|
24
|
+
end
|
25
|
+
|
26
|
+
def origin_url_parts
|
27
|
+
@origin_url_parts ||= origin_url.split(/[\/:]/)
|
28
|
+
end
|
29
|
+
|
30
|
+
def username
|
31
|
+
@username ||= origin_url_parts[-2] || ''
|
32
|
+
end
|
33
|
+
|
34
|
+
def repository
|
35
|
+
@repo ||= origin_url_parts[-1].sub(/\.git$/, '') || ''
|
36
|
+
end
|
37
|
+
|
38
|
+
def abort_for_non_github_repo
|
39
|
+
abort 'This does not appear to be a GitHub repository.'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
twig = Twig.new
|
44
|
+
twig.read_config_file!
|
45
|
+
twig.read_cli_options!(ARGV)
|
46
|
+
|
47
|
+
TwigGithubRepo.new do |gh_repo|
|
48
|
+
$stdout.sync = true
|
49
|
+
print 'Getting latest states for GitHub issues...'
|
50
|
+
|
51
|
+
issues = {}
|
52
|
+
issues_uri_base =
|
53
|
+
"https://api.github.com/repos/#{gh_repo.username}/#{gh_repo.repository}/issues"
|
54
|
+
issues_uris = [
|
55
|
+
URI.parse("#{issues_uri_base}?state=open"),
|
56
|
+
URI.parse("#{issues_uri_base}?state=closed")
|
57
|
+
]
|
58
|
+
|
59
|
+
begin
|
60
|
+
issues_uris.each do |issues_uri|
|
61
|
+
http = Net::HTTP.new(issues_uri.host, issues_uri.port)
|
62
|
+
http.use_ssl = true
|
63
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
64
|
+
request = Net::HTTP::Get.new(issues_uri.path + '?' + issues_uri.query)
|
65
|
+
response = http.request(request)
|
66
|
+
|
67
|
+
if response.code.to_i == 200
|
68
|
+
issues_data = JSON.parse(response.body)
|
69
|
+
issues_data.each do |issue_data|
|
70
|
+
issues[issue_data['number']] = issue_data
|
71
|
+
end
|
72
|
+
else
|
73
|
+
puts "\nERROR: Couldn't get open issues from GitHub. " <<
|
74
|
+
"(Response: #{response.code})"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
twig.branches.each do |branch|
|
80
|
+
issue_number = branch.get_property('issue').to_i
|
81
|
+
next unless issue_number > 0
|
82
|
+
|
83
|
+
issue = issues[issue_number]
|
84
|
+
next unless issue
|
85
|
+
|
86
|
+
state = issue['state']
|
87
|
+
branch.set_property('status', state) unless state.nil? || state.empty?
|
88
|
+
|
89
|
+
print '.'
|
90
|
+
end
|
91
|
+
|
92
|
+
puts
|
93
|
+
end
|
data/bin/twig-help
ADDED
data/install
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
twig_bin_path = File.expand_path(File.dirname(__FILE__)) + '/bin/**/twig*'
|
4
|
+
twig_bins = Dir.glob(twig_bin_path)
|
5
|
+
user_bin_path = '~/bin'
|
6
|
+
|
7
|
+
twig_bins.each do |bin|
|
8
|
+
`ln -fs #{bin} #{user_bin_path}`
|
9
|
+
end
|
10
|
+
|
11
|
+
if `which twig` && $?.success?
|
12
|
+
puts 'All set! Run `twig` to list your local branches.'
|
13
|
+
puts 'For more info, run `twig --help`.'
|
14
|
+
else
|
15
|
+
puts 'Argh! Something went wrong. Please try symlinking the files in '
|
16
|
+
puts '`./bin/` to `~/bin/` and ensure that `~/bin/` is in your `$PATH`, or '
|
17
|
+
puts 'contact rondevera on GitHub.'
|
18
|
+
end
|
data/lib/twig/branch.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
class Twig
|
2
|
+
class Branch
|
3
|
+
|
4
|
+
RESERVED_BRANCH_PROPERTIES = %w[merge rebase remote]
|
5
|
+
PROPERTY_NAME_FROM_GIT_CONFIG = /^branch\.[^.]+\.([^=]+)=.*$/
|
6
|
+
|
7
|
+
attr_accessor :name, :last_commit_time
|
8
|
+
|
9
|
+
def self.all_properties
|
10
|
+
@_all_properties ||= begin
|
11
|
+
config_lines = Twig.run('git config --list').split("\n")
|
12
|
+
|
13
|
+
properties = config_lines.map do |line|
|
14
|
+
# Split by rightmost `=`, allowing branch names to contain `=`:
|
15
|
+
key, value = line.match(/(.+)=(.+)/)[1..2]
|
16
|
+
|
17
|
+
key_parts = key.split('.')
|
18
|
+
key_parts.last if key_parts[0] == 'branch' && key_parts.size > 2
|
19
|
+
end.compact
|
20
|
+
|
21
|
+
properties.uniq.sort - RESERVED_BRANCH_PROPERTIES
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(name, attrs = {})
|
26
|
+
self.name = name
|
27
|
+
raise ArgumentError, '`name` is required' if name.empty?
|
28
|
+
|
29
|
+
self.last_commit_time = attrs[:last_commit_time]
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s ; name ; end
|
33
|
+
|
34
|
+
def sanitize_property(property_name)
|
35
|
+
property_name.gsub(/[ _]+/, '')
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_property(property_name)
|
39
|
+
Twig.run("git config branch.#{name}.#{property_name}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_property(property_name, value)
|
43
|
+
property_name = sanitize_property(property_name)
|
44
|
+
value = value.to_s.strip
|
45
|
+
|
46
|
+
if RESERVED_BRANCH_PROPERTIES.include?(property_name)
|
47
|
+
%{Can't modify the reserved property "#{property_name}".}
|
48
|
+
elsif value.empty?
|
49
|
+
%{Can't set a branch property to an empty string.}
|
50
|
+
else
|
51
|
+
Twig.run(%{git config branch.#{name}.#{property_name} "#{value}"})
|
52
|
+
result_body = %{property "#{property_name}" as "#{value}" for branch "#{name}".}
|
53
|
+
if $?.success?
|
54
|
+
"Saved #{result_body}"
|
55
|
+
else
|
56
|
+
"Could not save #{result_body}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def unset_property(property_name)
|
62
|
+
value = get_property(property_name)
|
63
|
+
if value && !value.empty?
|
64
|
+
Twig.run(%{git config --unset branch.#{name}.#{property_name}})
|
65
|
+
%{Removed property "#{property_name}" for branch "#{name}".}
|
66
|
+
else
|
67
|
+
%{The branch "#{name}" does not have the property "#{property_name}".}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|