rails-worktree 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +174 -0
- data/exe/worktree +5 -0
- data/lib/rails-worktree.rb +12 -0
- data/lib/worktree/cli.rb +59 -0
- data/lib/worktree/commands/close.rb +118 -0
- data/lib/worktree/commands/create.rb +42 -0
- data/lib/worktree/commands/init.rb +130 -0
- data/lib/worktree/railtie.rb +34 -0
- data/lib/worktree/tasks.rb +37 -0
- data/lib/worktree/version.rb +3 -0
- data/lib/worktree.rb +12 -0
- metadata +55 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e8888a53c51f48da7d20802a75aa290fedafb9a4facb449276ac98f03a35a2ca
|
|
4
|
+
data.tar.gz: a6609cd5f4d380f0c62acb8a7bae58079e9c995c032ef04efb2b815386edc612
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 28b6e35bbe05918a9ae07a794ce883e4c791e20f71d3fb1956b46a1b4c410ed7ee3f5c5382e914fcc2c90a5f78b25428b8a2a03a00a29c4b1191dce5df8d2706
|
|
7
|
+
data.tar.gz: d64ef8946b28c67a3f34e6602eed6903a8a2bb27492f576167453e2269ede2235e351ce985153495cb780e4469206da6a12d4274acf74a39b66fd81296e2d2e5
|
data/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Rails Worktree
|
|
2
|
+
|
|
3
|
+
A Ruby gem for managing git worktrees in Rails projects with isolated databases and configurations.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Create git worktrees with automatic branch creation
|
|
8
|
+
- Isolated database per worktree (separate database name)
|
|
9
|
+
- Automatic configuration file copying (.env, database.yml, etc.)
|
|
10
|
+
- Copy node_modules from main worktree
|
|
11
|
+
- Easy cleanup with database dropping and directory removal
|
|
12
|
+
- Works across any Rails project (no hardcoded paths)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### In your Rails project Gemfile
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
# Add to Gemfile (development group)
|
|
20
|
+
group :development do
|
|
21
|
+
gem "rails-worktree"
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Then run:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
bundle install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The gem will automatically install a binstub to `bin/worktree` when Rails loads in development mode.
|
|
32
|
+
|
|
33
|
+
### Manual binstub installation
|
|
34
|
+
|
|
35
|
+
If needed, you can manually install or reinstall the binstub:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bundle exec rake worktree:install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
To uninstall:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bundle exec rake worktree:uninstall
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Global installation (optional)
|
|
48
|
+
|
|
49
|
+
If you want to use `worktree` command globally:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
gem install rails-worktree
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
### Create a new worktree
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
bin/worktree feature-branch
|
|
61
|
+
# Creates worktree from current branch
|
|
62
|
+
|
|
63
|
+
bin/worktree feature-branch main
|
|
64
|
+
# Creates worktree from main branch
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This will:
|
|
68
|
+
1. Create a new git worktree in `../feature-branch`
|
|
69
|
+
2. Create a new branch called `feature-branch`
|
|
70
|
+
3. Copy configuration files from main worktree
|
|
71
|
+
4. Set up a separate database (e.g., `myapp_feature-branch`)
|
|
72
|
+
5. Copy node_modules
|
|
73
|
+
6. Run migrations and seed the database
|
|
74
|
+
|
|
75
|
+
### Close a worktree
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# From main repository:
|
|
79
|
+
bin/worktree --close feature-branch
|
|
80
|
+
|
|
81
|
+
# From within the worktree:
|
|
82
|
+
bin/worktree --close
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This will:
|
|
86
|
+
1. Drop the worktree's database
|
|
87
|
+
2. Remove the worktree directory
|
|
88
|
+
3. Delete the branch
|
|
89
|
+
4. Clean up git worktree references
|
|
90
|
+
|
|
91
|
+
### Manual initialization (advanced)
|
|
92
|
+
|
|
93
|
+
If you need to manually initialize a worktree:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cd ../feature-branch
|
|
97
|
+
worktree --init feature-branch
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## How it works
|
|
101
|
+
|
|
102
|
+
### Database isolation
|
|
103
|
+
|
|
104
|
+
The gem automatically:
|
|
105
|
+
- Detects your main database name from `config/database.yml`
|
|
106
|
+
- Creates a new database with pattern: `{app_name}_{worktree_name}`
|
|
107
|
+
- Updates the worktree's `.env` to set `DATABASE_NAME`
|
|
108
|
+
- Modifies `database.yml` to use the `DATABASE_NAME` environment variable
|
|
109
|
+
|
|
110
|
+
### Configuration files
|
|
111
|
+
|
|
112
|
+
The following files are copied from the main worktree:
|
|
113
|
+
- `.env`
|
|
114
|
+
- `config/database.yml`
|
|
115
|
+
- `Procfile.dev`
|
|
116
|
+
- `config/credentials/development.key`
|
|
117
|
+
|
|
118
|
+
### Node modules
|
|
119
|
+
|
|
120
|
+
If `node_modules` exists in the main worktree, it will be copied to the new worktree.
|
|
121
|
+
|
|
122
|
+
## Requirements
|
|
123
|
+
|
|
124
|
+
- Ruby >= 2.6.0
|
|
125
|
+
- Git with worktree support
|
|
126
|
+
- Rails project with standard structure
|
|
127
|
+
|
|
128
|
+
## Project structure
|
|
129
|
+
|
|
130
|
+
This gem works with Rails projects that follow the standard structure:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
your-project/
|
|
134
|
+
├── config/
|
|
135
|
+
│ ├── database.yml
|
|
136
|
+
│ └── credentials/
|
|
137
|
+
│ └── development.key
|
|
138
|
+
├── .env
|
|
139
|
+
├── Procfile.dev
|
|
140
|
+
└── bin/
|
|
141
|
+
├── rails
|
|
142
|
+
└── dev
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
To work on the gem:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Clone or create the gem
|
|
151
|
+
cd worktree
|
|
152
|
+
|
|
153
|
+
# Make changes to lib/worktree/**
|
|
154
|
+
|
|
155
|
+
# Test locally
|
|
156
|
+
gem build worktree.gemspec
|
|
157
|
+
gem install ./worktree-0.1.0.gem
|
|
158
|
+
|
|
159
|
+
# Test in a Rails project
|
|
160
|
+
cd /path/to/rails/project
|
|
161
|
+
worktree test-branch
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT
|
|
167
|
+
|
|
168
|
+
## Contributing
|
|
169
|
+
|
|
170
|
+
1. Fork it
|
|
171
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
172
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
173
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
174
|
+
5. Create new Pull Request
|
data/exe/worktree
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require_relative "worktree/version"
|
|
2
|
+
require_relative "worktree/cli"
|
|
3
|
+
require_relative "worktree/commands/create"
|
|
4
|
+
require_relative "worktree/commands/init"
|
|
5
|
+
require_relative "worktree/commands/close"
|
|
6
|
+
|
|
7
|
+
# Load Railtie only if Rails is available
|
|
8
|
+
require_relative "worktree/railtie" if defined?(Rails::Railtie)
|
|
9
|
+
|
|
10
|
+
module Worktree
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
end
|
data/lib/worktree/cli.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Worktree
|
|
2
|
+
class CLI
|
|
3
|
+
def self.run(args)
|
|
4
|
+
new(args).run
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def initialize(args)
|
|
8
|
+
@args = args
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
if @args.empty?
|
|
13
|
+
print_usage
|
|
14
|
+
exit 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
case @args[0]
|
|
18
|
+
when "--close", "close"
|
|
19
|
+
@args.shift
|
|
20
|
+
Commands::Close.new(@args).run
|
|
21
|
+
when "--init", "init"
|
|
22
|
+
@args.shift
|
|
23
|
+
Commands::Init.new(@args).run
|
|
24
|
+
when "--help", "-h", "help"
|
|
25
|
+
print_usage
|
|
26
|
+
else
|
|
27
|
+
# Default: create worktree
|
|
28
|
+
Commands::Create.new(@args).run
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def print_usage
|
|
35
|
+
puts <<~USAGE
|
|
36
|
+
Usage: worktree <name> [base-branch]
|
|
37
|
+
worktree --close [worktree-name]
|
|
38
|
+
worktree --init <worktree-name>
|
|
39
|
+
|
|
40
|
+
Creates a new git worktree and initializes it with configuration
|
|
41
|
+
|
|
42
|
+
Commands:
|
|
43
|
+
<name> Create a new worktree with the given name
|
|
44
|
+
--close [name] Close and remove a worktree
|
|
45
|
+
--init <name> Initialize a worktree (usually called automatically)
|
|
46
|
+
--help, -h Show this help message
|
|
47
|
+
|
|
48
|
+
Arguments:
|
|
49
|
+
<name> Name of the worktree (required)
|
|
50
|
+
[base-branch] Branch to create worktree from (default: current branch)
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
worktree feature-branch # Create new worktree
|
|
54
|
+
worktree --close feature-branch # Close worktree from main repo
|
|
55
|
+
worktree --close # Close worktree from within it
|
|
56
|
+
USAGE
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
|
|
3
|
+
module Worktree
|
|
4
|
+
module Commands
|
|
5
|
+
class Close
|
|
6
|
+
def initialize(args)
|
|
7
|
+
@worktree_name = args[0]
|
|
8
|
+
@main_worktree = get_main_worktree
|
|
9
|
+
@current_dir = Dir.pwd
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
detect_worktree_name unless @worktree_name
|
|
14
|
+
|
|
15
|
+
@db_prefix = get_db_prefix
|
|
16
|
+
@database_name = "#{@db_prefix}_#{@worktree_name}"
|
|
17
|
+
|
|
18
|
+
detect_paths
|
|
19
|
+
|
|
20
|
+
puts "Closing worktree '#{@worktree_name}'..."
|
|
21
|
+
puts "Main worktree: #{@main_worktree}"
|
|
22
|
+
puts ""
|
|
23
|
+
|
|
24
|
+
drop_database
|
|
25
|
+
remove_worktree
|
|
26
|
+
prune_worktrees
|
|
27
|
+
delete_branch
|
|
28
|
+
|
|
29
|
+
puts ""
|
|
30
|
+
puts "✓ Worktree '#{@worktree_name}' closed successfully!"
|
|
31
|
+
puts " Database #{@database_name} dropped"
|
|
32
|
+
puts " Worktree removed from #{@worktree_path}"
|
|
33
|
+
puts " Branch #{@worktree_name} deleted"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def get_main_worktree
|
|
39
|
+
output = `git worktree list --porcelain`
|
|
40
|
+
output.lines.grep(/^worktree /).first&.split(" ", 2)&.last&.strip
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def detect_worktree_name
|
|
44
|
+
if @current_dir == @main_worktree
|
|
45
|
+
puts "Error: You must specify a worktree name when running from the main repository"
|
|
46
|
+
puts "Usage: worktree --close <worktree-name>"
|
|
47
|
+
puts " or: cd to the worktree and run: worktree --close"
|
|
48
|
+
exit 1
|
|
49
|
+
else
|
|
50
|
+
@worktree_name = File.basename(@current_dir)
|
|
51
|
+
puts "Detected worktree name: #{@worktree_name}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def get_db_prefix
|
|
56
|
+
database_yml = File.join(@main_worktree, "config/database.yml")
|
|
57
|
+
return nil unless File.exist?(database_yml)
|
|
58
|
+
|
|
59
|
+
content = File.read(database_yml)
|
|
60
|
+
match = content.match(/database:\s*(\w+)_development/)
|
|
61
|
+
match ? match[1] : nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def detect_paths
|
|
65
|
+
if @current_dir == @main_worktree
|
|
66
|
+
@in_main_repo = true
|
|
67
|
+
@worktree_path = File.join(File.dirname(@main_worktree), @worktree_name)
|
|
68
|
+
@worktree_dir = @worktree_path
|
|
69
|
+
else
|
|
70
|
+
@in_main_repo = false
|
|
71
|
+
@worktree_path = @current_dir
|
|
72
|
+
@worktree_dir = "."
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def drop_database
|
|
77
|
+
puts "Dropping database #{@database_name}..."
|
|
78
|
+
|
|
79
|
+
Dir.chdir(@worktree_dir) do
|
|
80
|
+
env_file = ".env"
|
|
81
|
+
if File.exist?(env_file) && File.read(env_file).match?(/^DATABASE_NAME=#{@database_name}/)
|
|
82
|
+
system("RAILS_ENV=development bin/rails db:drop 2>/dev/null") ||
|
|
83
|
+
puts("Warning: Could not drop database #{@database_name}")
|
|
84
|
+
else
|
|
85
|
+
puts "Warning: DATABASE_NAME not set to #{@database_name} in .env, skipping database drop"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def remove_worktree
|
|
91
|
+
puts "Removing worktree..."
|
|
92
|
+
|
|
93
|
+
# Change back to main repo if needed
|
|
94
|
+
Dir.chdir(@main_worktree) unless @in_main_repo
|
|
95
|
+
|
|
96
|
+
if system("git worktree remove #{@worktree_path} --force 2>/dev/null")
|
|
97
|
+
puts "Worktree removed successfully via git"
|
|
98
|
+
else
|
|
99
|
+
puts "Git worktree remove failed, deleting directory manually..."
|
|
100
|
+
if Dir.exist?(@worktree_path)
|
|
101
|
+
FileUtils.rm_rf(@worktree_path)
|
|
102
|
+
puts "Directory deleted: #{@worktree_path}"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def prune_worktrees
|
|
108
|
+
system("git worktree prune")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def delete_branch
|
|
112
|
+
puts "Deleting branch #{@worktree_name}..."
|
|
113
|
+
system("git branch -D #{@worktree_name} 2>/dev/null") ||
|
|
114
|
+
puts("Warning: Could not delete branch #{@worktree_name}")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Worktree
|
|
2
|
+
module Commands
|
|
3
|
+
class Create
|
|
4
|
+
def initialize(args)
|
|
5
|
+
@worktree_name = args[0]
|
|
6
|
+
@base_branch = args[1]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def run
|
|
10
|
+
unless @worktree_name
|
|
11
|
+
puts "Error: Worktree name is required"
|
|
12
|
+
exit 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@base_branch ||= current_branch
|
|
16
|
+
worktree_path = "../#{@worktree_name}"
|
|
17
|
+
|
|
18
|
+
puts "Creating worktree '#{@worktree_name}' from branch '#{@base_branch}' at #{worktree_path}..."
|
|
19
|
+
|
|
20
|
+
unless system("git worktree add -b #{@worktree_name} #{worktree_path} #{@base_branch}")
|
|
21
|
+
puts "Failed to create worktree"
|
|
22
|
+
exit 1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
puts ""
|
|
26
|
+
puts "✓ Worktree created at #{worktree_path}"
|
|
27
|
+
puts ""
|
|
28
|
+
puts "Initializing worktree..."
|
|
29
|
+
|
|
30
|
+
Dir.chdir(worktree_path) do
|
|
31
|
+
Init.new([@worktree_name]).run
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def current_branch
|
|
38
|
+
`git branch --show-current`.strip
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
|
|
3
|
+
module Worktree
|
|
4
|
+
module Commands
|
|
5
|
+
class Init
|
|
6
|
+
def initialize(args)
|
|
7
|
+
@worktree_name = args[0]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def run
|
|
11
|
+
unless @worktree_name
|
|
12
|
+
puts "Error: Worktree name is required"
|
|
13
|
+
puts "Usage: worktree --init <worktree-name>"
|
|
14
|
+
exit 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@main_worktree = get_main_worktree
|
|
18
|
+
@db_prefix = get_db_prefix
|
|
19
|
+
@database_name = "#{@db_prefix}_#{@worktree_name}"
|
|
20
|
+
|
|
21
|
+
puts "Initializing worktree '#{@worktree_name}'..."
|
|
22
|
+
puts "Main worktree: #{@main_worktree}"
|
|
23
|
+
puts "Database: #{@database_name}"
|
|
24
|
+
|
|
25
|
+
copy_config_files
|
|
26
|
+
set_database_name
|
|
27
|
+
update_database_yml
|
|
28
|
+
copy_node_modules
|
|
29
|
+
setup_database
|
|
30
|
+
|
|
31
|
+
puts ""
|
|
32
|
+
puts "✓ Worktree initialized successfully!"
|
|
33
|
+
puts " Database: #{@database_name}"
|
|
34
|
+
puts " Configuration files copied"
|
|
35
|
+
puts ""
|
|
36
|
+
puts "To start the development server: bin/dev"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def get_main_worktree
|
|
42
|
+
output = `git worktree list --porcelain`
|
|
43
|
+
output.lines.grep(/^worktree /).first&.split(" ", 2)&.last&.strip
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_db_prefix
|
|
47
|
+
database_yml = File.join(@main_worktree, "config/database.yml")
|
|
48
|
+
return nil unless File.exist?(database_yml)
|
|
49
|
+
|
|
50
|
+
content = File.read(database_yml)
|
|
51
|
+
match = content.match(/database:\s*(\w+)_development/)
|
|
52
|
+
match ? match[1] : nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def copy_config_files
|
|
56
|
+
puts "Copying configuration files..."
|
|
57
|
+
|
|
58
|
+
files_to_copy = [
|
|
59
|
+
".env",
|
|
60
|
+
"config/database.yml",
|
|
61
|
+
"Procfile.dev",
|
|
62
|
+
"config/credentials/development.key"
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
files_to_copy.each do |file|
|
|
66
|
+
source = File.join(@main_worktree, file)
|
|
67
|
+
if File.exist?(source)
|
|
68
|
+
FileUtils.mkdir_p(File.dirname(file)) unless File.directory?(File.dirname(file))
|
|
69
|
+
FileUtils.cp(source, file)
|
|
70
|
+
else
|
|
71
|
+
puts "Warning: #{file} not found, skipping"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def set_database_name
|
|
77
|
+
puts "Setting DATABASE_NAME=#{@database_name} in .env..."
|
|
78
|
+
|
|
79
|
+
env_file = ".env"
|
|
80
|
+
return unless File.exist?(env_file)
|
|
81
|
+
|
|
82
|
+
content = File.read(env_file)
|
|
83
|
+
if content.match?(/^DATABASE_NAME=/)
|
|
84
|
+
content.gsub!(/^DATABASE_NAME=.*$/, "DATABASE_NAME=#{@database_name}")
|
|
85
|
+
else
|
|
86
|
+
content += "\nDATABASE_NAME=#{@database_name}\n"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
File.write(env_file, content)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def update_database_yml
|
|
93
|
+
puts "Updating database.yml to use DATABASE_NAME..."
|
|
94
|
+
|
|
95
|
+
database_yml = "config/database.yml"
|
|
96
|
+
return unless File.exist?(database_yml)
|
|
97
|
+
|
|
98
|
+
content = File.read(database_yml)
|
|
99
|
+
content.gsub!(
|
|
100
|
+
/database:\s*#{@db_prefix}_development/,
|
|
101
|
+
"database: <%= ENV.fetch(\"DATABASE_NAME\", \"#{@db_prefix}_development\") %>"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
File.write(database_yml, content)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def copy_node_modules
|
|
108
|
+
source = File.join(@main_worktree, "node_modules")
|
|
109
|
+
dest = "node_modules"
|
|
110
|
+
|
|
111
|
+
if Dir.exist?(source) && !Dir.exist?(dest)
|
|
112
|
+
puts "Copying node_modules from main worktree..."
|
|
113
|
+
FileUtils.cp_r(source, dest)
|
|
114
|
+
puts "Note: node_modules copied."
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def setup_database
|
|
119
|
+
puts "Creating database #{@database_name}..."
|
|
120
|
+
system("RAILS_ENV=development bin/rails db:create") || puts("Warning: Could not create database")
|
|
121
|
+
|
|
122
|
+
puts "Running migrations..."
|
|
123
|
+
system("RAILS_ENV=development bin/rails db:migrate") || puts("Warning: Could not run migrations")
|
|
124
|
+
|
|
125
|
+
puts "Seeding database..."
|
|
126
|
+
system("RAILS_ENV=development bin/rails db:seed") || puts("Warning: Could not seed database")
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require "rails/railtie"
|
|
2
|
+
|
|
3
|
+
module Worktree
|
|
4
|
+
class Railtie < Rails::Railtie
|
|
5
|
+
railtie_name :worktree
|
|
6
|
+
|
|
7
|
+
rake_tasks do
|
|
8
|
+
load "worktree/tasks.rb"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
initializer "worktree.install_binstub" do
|
|
12
|
+
# Install binstub automatically when Rails loads in development
|
|
13
|
+
if Rails.env.development?
|
|
14
|
+
binstub_path = Rails.root.join("bin/worktree")
|
|
15
|
+
|
|
16
|
+
unless File.exist?(binstub_path)
|
|
17
|
+
Rails.logger.info "Installing worktree binstub to bin/worktree..."
|
|
18
|
+
|
|
19
|
+
File.write(binstub_path, <<~RUBY)
|
|
20
|
+
#!/usr/bin/env ruby
|
|
21
|
+
|
|
22
|
+
require "bundler/setup"
|
|
23
|
+
require "worktree"
|
|
24
|
+
|
|
25
|
+
Worktree::CLI.run(ARGV)
|
|
26
|
+
RUBY
|
|
27
|
+
|
|
28
|
+
FileUtils.chmod("+x", binstub_path)
|
|
29
|
+
Rails.logger.info "✓ Worktree binstub installed! Use: bin/worktree <name>"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
namespace :worktree do
|
|
2
|
+
desc "Install worktree binstub to bin/worktree"
|
|
3
|
+
task :install do
|
|
4
|
+
binstub_path = File.join(Dir.pwd, "bin/worktree")
|
|
5
|
+
|
|
6
|
+
if File.exist?(binstub_path)
|
|
7
|
+
puts "Binstub already exists at bin/worktree"
|
|
8
|
+
exit 0
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
File.write(binstub_path, <<~RUBY)
|
|
12
|
+
#!/usr/bin/env ruby
|
|
13
|
+
|
|
14
|
+
require "bundler/setup"
|
|
15
|
+
require "worktree"
|
|
16
|
+
|
|
17
|
+
Worktree::CLI.run(ARGV)
|
|
18
|
+
RUBY
|
|
19
|
+
|
|
20
|
+
File.chmod(0755, binstub_path)
|
|
21
|
+
|
|
22
|
+
puts "✓ Worktree binstub installed to bin/worktree"
|
|
23
|
+
puts "Usage: bin/worktree <name>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc "Uninstall worktree binstub from bin/worktree"
|
|
27
|
+
task :uninstall do
|
|
28
|
+
binstub_path = File.join(Dir.pwd, "bin/worktree")
|
|
29
|
+
|
|
30
|
+
if File.exist?(binstub_path)
|
|
31
|
+
File.delete(binstub_path)
|
|
32
|
+
puts "✓ Worktree binstub removed from bin/worktree"
|
|
33
|
+
else
|
|
34
|
+
puts "Binstub not found at bin/worktree"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/worktree.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require_relative "worktree/version"
|
|
2
|
+
require_relative "worktree/cli"
|
|
3
|
+
require_relative "worktree/commands/create"
|
|
4
|
+
require_relative "worktree/commands/init"
|
|
5
|
+
require_relative "worktree/commands/close"
|
|
6
|
+
|
|
7
|
+
# Load Railtie only if Rails is available
|
|
8
|
+
require_relative "worktree/railtie" if defined?(Rails::Railtie)
|
|
9
|
+
|
|
10
|
+
module Worktree
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rails-worktree
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Martin Ulleberg
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Easily create, initialize, and close git worktrees with isolated databases
|
|
13
|
+
and configurations for Rails projects
|
|
14
|
+
email:
|
|
15
|
+
- martin@fasttravel.com
|
|
16
|
+
executables:
|
|
17
|
+
- worktree
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- README.md
|
|
22
|
+
- exe/worktree
|
|
23
|
+
- lib/rails-worktree.rb
|
|
24
|
+
- lib/worktree.rb
|
|
25
|
+
- lib/worktree/cli.rb
|
|
26
|
+
- lib/worktree/commands/close.rb
|
|
27
|
+
- lib/worktree/commands/create.rb
|
|
28
|
+
- lib/worktree/commands/init.rb
|
|
29
|
+
- lib/worktree/railtie.rb
|
|
30
|
+
- lib/worktree/tasks.rb
|
|
31
|
+
- lib/worktree/version.rb
|
|
32
|
+
homepage: https://github.com/FastTravelAS/rails-worktree
|
|
33
|
+
licenses:
|
|
34
|
+
- MIT
|
|
35
|
+
metadata:
|
|
36
|
+
homepage_uri: https://github.com/FastTravelAS/rails-worktree
|
|
37
|
+
source_code_uri: https://github.com/FastTravelAS/rails-worktree
|
|
38
|
+
rdoc_options: []
|
|
39
|
+
require_paths:
|
|
40
|
+
- lib
|
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 2.6.0
|
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '0'
|
|
51
|
+
requirements: []
|
|
52
|
+
rubygems_version: 3.6.9
|
|
53
|
+
specification_version: 4
|
|
54
|
+
summary: Git worktree management for Rails projects
|
|
55
|
+
test_files: []
|