worktree 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/worktree.rb +1 -5
- data/lib/worktree/cli.rb +7 -0
- data/lib/worktree/command/add.rb +5 -10
- data/lib/worktree/command/cherry_pick.rb +5 -10
- data/lib/worktree/command/init.rb +51 -0
- data/lib/worktree/command/open.rb +3 -15
- data/lib/worktree/command/remove.rb +1 -1
- data/lib/worktree/command/remove_stale.rb +1 -1
- data/lib/worktree/launcher.rb +29 -0
- data/lib/worktree/tab_completion/branch_completion.rb +4 -1
- data/lib/worktree/version.rb +1 -1
- metadata +11 -10
- data/lib/worktree/feature/jira.rb +0 -74
- data/lib/worktree/feature/tmux.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae13288c9a0d09cf33b342bbcbd6cba9153713f5589afd88578f828d74e781f2
|
4
|
+
data.tar.gz: 58195a0bddf0d7c7310e8fdc01cf5a890f4006c57ea638754435cb82ad5380a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8c31028b7da48adf4137fe78b1b66c35d708c6ec78cb10f579540bb3a358c0fa00203d7768151d81eef1e09be9fc3ac102da87f6c604f003d082f5aedf1effd
|
7
|
+
data.tar.gz: ba0eff802cf57b7ea745a54a08a1fe2c845bdbbd30622a0de2aaba1316c035a61796013ebe5bfe163d2e61fa5c4bfd6a446e794fc938237ff5715e9d3853ae20
|
data/lib/worktree.rb
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'logger'
|
4
4
|
require 'tty-command'
|
5
|
-
|
6
|
-
require 'active_support/core_ext'
|
5
|
+
require 'active_support/all'
|
7
6
|
require 'git'
|
8
7
|
require 'zeitwerk'
|
9
8
|
|
@@ -11,9 +10,6 @@ loader = Zeitwerk::Loader.for_gem
|
|
11
10
|
loader.setup
|
12
11
|
|
13
12
|
module Worktree
|
14
|
-
JIRA_ISSUE_ID_REGEX_TEMPLATE = ENV.fetch('JIRA_ISSUE_ID_REGEX') { '^\w\-\d+' }
|
15
|
-
JIRA_ISSUE_ID_REGEX = Regexp.new(JIRA_ISSUE_ID_REGEX_TEMPLATE)
|
16
|
-
|
17
13
|
def logger
|
18
14
|
return @logger if defined?(@logger)
|
19
15
|
|
data/lib/worktree/cli.rb
CHANGED
@@ -55,5 +55,12 @@ module Worktree
|
|
55
55
|
def configure
|
56
56
|
Worktree::Command::Configure.new.do!
|
57
57
|
end
|
58
|
+
|
59
|
+
desc 'init URI', 'Initialize new worktree'
|
60
|
+
option :repo_path, required: true
|
61
|
+
def init(uri)
|
62
|
+
Worktree::Command::Init.new(uri,
|
63
|
+
repo_path: options[:repo_path]).do!
|
64
|
+
end
|
58
65
|
end
|
59
66
|
end
|
data/lib/worktree/command/add.rb
CHANGED
@@ -10,7 +10,7 @@ module Worktree
|
|
10
10
|
def initialize(branch, from:, project_dir:)
|
11
11
|
@branch = branch
|
12
12
|
@branch_remote = from
|
13
|
-
@project_dir = project_dir || Project.resolve(branch).root
|
13
|
+
@project_dir = File.expand_path project_dir || Project.resolve(branch).root
|
14
14
|
@worktree = "#{@project_dir}/#{@branch}"
|
15
15
|
end
|
16
16
|
|
@@ -29,7 +29,10 @@ module Worktree
|
|
29
29
|
|
30
30
|
copy_files
|
31
31
|
clone_dbs
|
32
|
-
|
32
|
+
Launcher.new(
|
33
|
+
project_dir: @project_dir,
|
34
|
+
branch: @branch
|
35
|
+
).launch!
|
33
36
|
end
|
34
37
|
|
35
38
|
private
|
@@ -50,14 +53,6 @@ module Worktree
|
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
53
|
-
def tmux
|
54
|
-
tmux_session_name = @branch.tr('.', '-')
|
55
|
-
Feature::Tmux.new(
|
56
|
-
project_dir: @project_dir,
|
57
|
-
branch: @branch
|
58
|
-
).run!(tmux_session_name)
|
59
|
-
end
|
60
|
-
|
61
56
|
def git
|
62
57
|
@git ||= Worktree.git_for(@project_dir)
|
63
58
|
end
|
@@ -10,7 +10,7 @@ module Worktree
|
|
10
10
|
@commit = commit[0..7] # short commit
|
11
11
|
@branch_remote = to
|
12
12
|
@branch = "cherry-pick-#{@commit}-to-#{@branch_remote.tr('/', '-')}"
|
13
|
-
@project_dir = project_dir
|
13
|
+
@project_dir = File.expand_path project_dir
|
14
14
|
end
|
15
15
|
|
16
16
|
def do!
|
@@ -31,7 +31,10 @@ module Worktree
|
|
31
31
|
|
32
32
|
copy_files
|
33
33
|
clone_dbs
|
34
|
-
|
34
|
+
Launcher.new(
|
35
|
+
project_dir: @project_dir,
|
36
|
+
branch: @branch
|
37
|
+
).launch!
|
35
38
|
end
|
36
39
|
|
37
40
|
private
|
@@ -52,14 +55,6 @@ module Worktree
|
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
|
-
def tmux
|
56
|
-
tmux_session_name = @branch.tr('.', '-')
|
57
|
-
Feature::Tmux.new(
|
58
|
-
project_dir: @project_dir,
|
59
|
-
branch: @branch
|
60
|
-
).run!(tmux_session_name)
|
61
|
-
end
|
62
|
-
|
63
58
|
def git
|
64
59
|
@git ||= Worktree.git_for(@project_dir)
|
65
60
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tty-prompt'
|
4
|
+
|
5
|
+
module Worktree
|
6
|
+
module Command
|
7
|
+
class Init
|
8
|
+
def initialize(uri, repo_path:)
|
9
|
+
@uri = uri
|
10
|
+
@repo_path = File.expand_path repo_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def do!
|
14
|
+
# clone git repo
|
15
|
+
@git = Git.clone(@uri, tmp_repo_name, path: @repo_path)
|
16
|
+
|
17
|
+
# rearrange repo folders
|
18
|
+
FileUtils.mkdir_p "#{@repo_path}/#{repo_name}"
|
19
|
+
git_master_path = "#{@repo_path}/#{repo_name}/master"
|
20
|
+
FileUtils.mv "#{@repo_path}/#{tmp_repo_name}", git_master_path
|
21
|
+
|
22
|
+
# reinit git from new path
|
23
|
+
@git = Worktree.git_for(git_master_path)
|
24
|
+
|
25
|
+
remote_name = TTY::Prompt.new.ask?('What is remote name?', default: 'origin')
|
26
|
+
|
27
|
+
unless remote_name == 'origin'
|
28
|
+
# add remote
|
29
|
+
@git.add_remote remote_name, @uri
|
30
|
+
|
31
|
+
# TODO: remove origin remote?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# example '123' * 2 = '123123'
|
38
|
+
def tmp_repo_name
|
39
|
+
repo_name * 2
|
40
|
+
end
|
41
|
+
|
42
|
+
def repo_name
|
43
|
+
@repo_name ||= begin
|
44
|
+
u = URI(@uri)
|
45
|
+
n = u.path.split('/')
|
46
|
+
n.last[0..-5] # remove .git
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -7,7 +7,7 @@ module Worktree
|
|
7
7
|
class Open
|
8
8
|
def initialize(branch, project_dir:)
|
9
9
|
@branch = branch
|
10
|
-
@project_dir = project_dir || Project.resolve(branch).root
|
10
|
+
@project_dir = File.expand_path project_dir || Project.resolve(branch).root
|
11
11
|
@worktree = "#{@project_dir}/#{@branch}"
|
12
12
|
end
|
13
13
|
|
@@ -15,22 +15,10 @@ module Worktree
|
|
15
15
|
raise "Worktree #{@worktree} not found exists!" unless Dir.exist?(@worktree)
|
16
16
|
raise 'No master repo found!' unless Dir.exist?("#{@project_dir}/master/.git")
|
17
17
|
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def tmux
|
24
|
-
project_dir_name = File.expand_path(@project_dir).chomp('/').split('/').last
|
25
|
-
tmux_session_name = if @branch == 'master'
|
26
|
-
"#{project_dir_name}-#{@branch}"
|
27
|
-
else
|
28
|
-
@branch
|
29
|
-
end
|
30
|
-
Feature::Tmux.new(
|
18
|
+
Launcher.new(
|
31
19
|
project_dir: @project_dir,
|
32
20
|
branch: @branch
|
33
|
-
).
|
21
|
+
).launch!
|
34
22
|
end
|
35
23
|
end
|
36
24
|
end
|
@@ -5,7 +5,7 @@ module Worktree
|
|
5
5
|
class Remove
|
6
6
|
def initialize(branch, project_dir:, update_refs: true)
|
7
7
|
@branch = branch
|
8
|
-
@project_dir = project_dir || Project.resolve(branch).root
|
8
|
+
@project_dir = File.expand_path project_dir || Project.resolve(branch).root
|
9
9
|
@worktree = "#{@project_dir}/#{@branch}"
|
10
10
|
@update_refs = update_refs
|
11
11
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Worktree
|
4
|
+
class Launcher # :nodoc:
|
5
|
+
def initialize(project_dir:, branch:)
|
6
|
+
@project_dir = project_dir
|
7
|
+
@branch = branch
|
8
|
+
@working_directory = "#{@project_dir}/#{@branch}".chomp('/')
|
9
|
+
end
|
10
|
+
|
11
|
+
def launch!
|
12
|
+
Dir.chdir(@working_directory) { Kernel.system(command) }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def command
|
18
|
+
cmd = ENV.fetch('WORKTREE_LAUNCHER') { ENV.fetch('EDITOR', 'vim') }
|
19
|
+
format(cmd, replace_vars)
|
20
|
+
end
|
21
|
+
|
22
|
+
def replace_vars
|
23
|
+
{
|
24
|
+
worktree_dir: @working_directory,
|
25
|
+
worktree_branch: @branch
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -5,6 +5,9 @@ require 'jira-ruby'
|
|
5
5
|
module Worktree
|
6
6
|
module TabCompletion
|
7
7
|
class BranchCompletion
|
8
|
+
JIRA_ISSUE_ID_REGEX_TEMPLATE = ENV.fetch('JIRA_ISSUE_ID_REGEX') { '^\w\-\d+' }
|
9
|
+
JIRA_ISSUE_ID_REGEX = Regexp.new(JIRA_ISSUE_ID_REGEX_TEMPLATE)
|
10
|
+
|
8
11
|
def initialize(compl)
|
9
12
|
@compl = compl
|
10
13
|
end
|
@@ -22,7 +25,7 @@ module Worktree
|
|
22
25
|
private
|
23
26
|
|
24
27
|
def find_jira_issue_by(comp_line)
|
25
|
-
(comp_line.match(
|
28
|
+
(comp_line.match(JIRA_ISSUE_ID_REGEX) || [])[0]
|
26
29
|
end
|
27
30
|
|
28
31
|
def jira_client
|
data/lib/worktree/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: worktree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Gonchar
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -178,7 +178,7 @@ dependencies:
|
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
-
description:
|
181
|
+
description:
|
182
182
|
email:
|
183
183
|
- igor.gonchar@gmail.com
|
184
184
|
executables:
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- lib/worktree/command/add.rb
|
198
198
|
- lib/worktree/command/cherry_pick.rb
|
199
199
|
- lib/worktree/command/configure.rb
|
200
|
+
- lib/worktree/command/init.rb
|
200
201
|
- lib/worktree/command/open.rb
|
201
202
|
- lib/worktree/command/remove.rb
|
202
203
|
- lib/worktree/command/remove_stale.rb
|
@@ -205,8 +206,7 @@ files:
|
|
205
206
|
- lib/worktree/error.rb
|
206
207
|
- lib/worktree/feature/clone_dbs.rb
|
207
208
|
- lib/worktree/feature/copy_files.rb
|
208
|
-
- lib/worktree/
|
209
|
-
- lib/worktree/feature/tmux.rb
|
209
|
+
- lib/worktree/launcher.rb
|
210
210
|
- lib/worktree/project.rb
|
211
211
|
- lib/worktree/tab_completion.rb
|
212
212
|
- lib/worktree/tab_completion/branch_completion.rb
|
@@ -219,7 +219,7 @@ homepage: https://github.com/gigorok/worktree
|
|
219
219
|
licenses:
|
220
220
|
- MIT
|
221
221
|
metadata: {}
|
222
|
-
post_install_message:
|
222
|
+
post_install_message:
|
223
223
|
rdoc_options: []
|
224
224
|
require_paths:
|
225
225
|
- lib
|
@@ -227,15 +227,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
227
227
|
requirements:
|
228
228
|
- - ">="
|
229
229
|
- !ruby/object:Gem::Version
|
230
|
-
version:
|
230
|
+
version: 2.4.4
|
231
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
232
232
|
requirements:
|
233
233
|
- - ">="
|
234
234
|
- !ruby/object:Gem::Version
|
235
235
|
version: '0'
|
236
236
|
requirements: []
|
237
|
-
|
238
|
-
|
237
|
+
rubyforge_project:
|
238
|
+
rubygems_version: 2.7.6.2
|
239
|
+
signing_key:
|
239
240
|
specification_version: 4
|
240
241
|
summary: Manage your projects by git working tree feature
|
241
242
|
test_files: []
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'jira-ruby'
|
4
|
-
|
5
|
-
module Worktree
|
6
|
-
module Feature
|
7
|
-
class Jira
|
8
|
-
def initialize(project_dir:, branch:)
|
9
|
-
@project_dir = project_dir
|
10
|
-
@branch = branch
|
11
|
-
end
|
12
|
-
|
13
|
-
def run!
|
14
|
-
if jira_issue?
|
15
|
-
prompt = "Jira issue #{jira_issue_id} status: #{jira_issue.status.name}. Would you like to change it?"
|
16
|
-
jira_process! unless TTY::Prompt.new.no?(prompt)
|
17
|
-
end
|
18
|
-
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def jira_client
|
25
|
-
@jira_client ||= JIRA::Client.new(jira_client_options)
|
26
|
-
end
|
27
|
-
|
28
|
-
def jira_client_options
|
29
|
-
{
|
30
|
-
username: ENV['JIRA_USERNAME'],
|
31
|
-
password: ENV['JIRA_PASSWORD'],
|
32
|
-
site: ENV['JIRA_SITE'],
|
33
|
-
context_path: '',
|
34
|
-
auth_type: :basic
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
|
-
def jira_issue?
|
39
|
-
return false unless jira_issue_id
|
40
|
-
|
41
|
-
jira_issue_id =~ Worktree::JIRA_ISSUE_ID_REGEX
|
42
|
-
end
|
43
|
-
|
44
|
-
def jira_process!
|
45
|
-
transition = choose_transition
|
46
|
-
apply_transition!(transition) if transition != -1
|
47
|
-
rescue StandardError => e
|
48
|
-
Worktree.logger.error { e.message }
|
49
|
-
end
|
50
|
-
|
51
|
-
def jira_issue_id
|
52
|
-
(@branch.match(/^\w+\-\d+/) || [])[0]
|
53
|
-
end
|
54
|
-
|
55
|
-
def jira_issue
|
56
|
-
@jira_issue ||= jira_client.Issue.find(jira_issue_id)
|
57
|
-
end
|
58
|
-
|
59
|
-
def apply_transition!(transition)
|
60
|
-
jira_issue.transitions.build.save!(transition: { id: transition.id })
|
61
|
-
end
|
62
|
-
|
63
|
-
def choose_transition
|
64
|
-
TTY::Prompt.new.select('Choose a transition?', cycle: true) do |menu|
|
65
|
-
menu.enum '.'
|
66
|
-
menu.choice 'Skip it', -1
|
67
|
-
jira_issue.transitions.all.each do |s|
|
68
|
-
menu.choice s.name, s
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Worktree
|
4
|
-
module Feature
|
5
|
-
class Tmux
|
6
|
-
|
7
|
-
class VimEditor
|
8
|
-
attr_reader :window_name
|
9
|
-
|
10
|
-
def initialize(cwd:)
|
11
|
-
@cwd = cwd
|
12
|
-
@window_name = 'vim'
|
13
|
-
end
|
14
|
-
|
15
|
-
# open Gemfile if present
|
16
|
-
def cmd
|
17
|
-
if File.exist?("#{@cwd}/Gemfile")
|
18
|
-
'vim Gemfile'
|
19
|
-
else
|
20
|
-
'vim'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def initialize(project_dir:, branch:)
|
26
|
-
@project_dir = project_dir
|
27
|
-
@branch = branch
|
28
|
-
@working_directory = "#{@project_dir}/#{@branch}".chomp('/')
|
29
|
-
end
|
30
|
-
|
31
|
-
def run!(session_name)
|
32
|
-
if session_exist?(session_name)
|
33
|
-
Worktree.logger.info { "TMUX session #{session_name} already exist" }
|
34
|
-
# TODO: ask for attach to it
|
35
|
-
return
|
36
|
-
end
|
37
|
-
|
38
|
-
Worktree.run_command "tmux new-session -t #{session_name} -d", chdir: @working_directory
|
39
|
-
Worktree.run_command "tmux new-window -d -t #{session_name} -n #{editor.window_name}", chdir: @working_directory
|
40
|
-
Worktree.run_command "tmux send-keys -t #{session_name}:2 \"#{editor.cmd}\" C-m"
|
41
|
-
Worktree.run_command "tmux select-window -t #{session_name}:2" # select vim window
|
42
|
-
if inside_tmux?
|
43
|
-
Kernel.system "tmux switch -t #{session_name}"
|
44
|
-
else
|
45
|
-
Kernel.system "tmux attach-session -t #{session_name}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def editor
|
52
|
-
return @editor if defined?(@editor)
|
53
|
-
|
54
|
-
@editor = VimEditor.new(cwd: @working_directory)
|
55
|
-
end
|
56
|
-
|
57
|
-
def inside_tmux?
|
58
|
-
Worktree.run_command('echo $TMUX').out.strip.present?
|
59
|
-
end
|
60
|
-
|
61
|
-
def session_exist?(name)
|
62
|
-
cmd = "tmux list-sessions -F '#S' | awk '/'#{name}/' {print $1}'"
|
63
|
-
Worktree.run_command(cmd).out.strip.present?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|