worktree 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|