easy-worktree 0.1.5__tar.gz → 0.1.7__tar.gz
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.
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/PKG-INFO +1 -1
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/easy_worktree/__init__.py +76 -7
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/pyproject.toml +1 -1
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/tests/test_integration.py +23 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/uv.lock +1 -1
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/.gitignore +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/.python-version +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/DEPLOY.md +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/GEMINI.md +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/LICENSE +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/README.md +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/README_ja.md +0 -0
- {easy_worktree-0.1.5 → easy_worktree-0.1.7}/hero.png +0 -0
|
@@ -28,8 +28,16 @@ MESSAGES = {
|
|
|
28
28
|
"ja": "使用方法: wt clone <repository_url>",
|
|
29
29
|
},
|
|
30
30
|
"usage_add": {
|
|
31
|
-
"en": "Usage: wt add (ad) <work_name> [<base_branch>] [--no-setup] [--select]",
|
|
32
|
-
"ja": "使用方法: wt add (ad) <作業名> [<base_branch>] [--no-setup] [--select]",
|
|
31
|
+
"en": "Usage: wt add (ad) <work_name> [<base_branch>] [--no-setup] [--select [<command>...]]",
|
|
32
|
+
"ja": "使用方法: wt add (ad) <作業名> [<base_branch>] [--no-setup] [--select [<コマンド>...]]",
|
|
33
|
+
},
|
|
34
|
+
"usage_select": {
|
|
35
|
+
"en": "Usage: wt select (sl) [<name>|-] [<command>...]",
|
|
36
|
+
"ja": "使用方法: wt select (sl) [<名前>|-] [<コマンド>...]",
|
|
37
|
+
},
|
|
38
|
+
"usage_run": {
|
|
39
|
+
"en": "Usage: wt run <name> <command>...",
|
|
40
|
+
"ja": "使用方法: wt run <名前> <コマンド>...",
|
|
33
41
|
},
|
|
34
42
|
"usage_rm": {"en": "Usage: wt rm <work_name>", "ja": "使用方法: wt rm <作業名>"},
|
|
35
43
|
"base_not_found": {
|
|
@@ -879,6 +887,16 @@ def cmd_add(args: list[str]):
|
|
|
879
887
|
|
|
880
888
|
work_name = clean_args[0]
|
|
881
889
|
branch_to_use = clean_args[1] if len(clean_args) >= 2 else None
|
|
890
|
+
|
|
891
|
+
# --select 以降をコマンドとして扱う
|
|
892
|
+
select_command = None
|
|
893
|
+
if select:
|
|
894
|
+
try:
|
|
895
|
+
select_idx = args.index("--select")
|
|
896
|
+
if select_idx + 1 < len(args):
|
|
897
|
+
select_command = args[select_idx + 1:]
|
|
898
|
+
except ValueError:
|
|
899
|
+
pass
|
|
882
900
|
|
|
883
901
|
base_dir = find_base_dir()
|
|
884
902
|
wt_path = add_worktree(work_name, branch_to_use=branch_to_use, skip_setup=skip_setup, base_dir=base_dir)
|
|
@@ -901,7 +919,7 @@ def cmd_add(args: list[str]):
|
|
|
901
919
|
current_sel = "main" if p == resolved_base else p.name
|
|
902
920
|
break
|
|
903
921
|
|
|
904
|
-
switch_selection(work_name, base_dir, current_sel, last_sel_file)
|
|
922
|
+
switch_selection(work_name, base_dir, current_sel, last_sel_file, command=select_command)
|
|
905
923
|
|
|
906
924
|
|
|
907
925
|
def cmd_stash(args: list[str]):
|
|
@@ -1504,6 +1522,7 @@ def cmd_select(args: list[str]):
|
|
|
1504
1522
|
return
|
|
1505
1523
|
|
|
1506
1524
|
target = args[0]
|
|
1525
|
+
command = args[1:] if len(args) > 1 else None
|
|
1507
1526
|
|
|
1508
1527
|
if target == "-":
|
|
1509
1528
|
if not last_sel_file.exists():
|
|
@@ -1518,7 +1537,46 @@ def cmd_select(args: list[str]):
|
|
|
1518
1537
|
print(msg("error", msg("select_not_found", target)), file=sys.stderr)
|
|
1519
1538
|
sys.exit(1)
|
|
1520
1539
|
|
|
1521
|
-
switch_selection(target, base_dir, current_sel, last_sel_file)
|
|
1540
|
+
switch_selection(target, base_dir, current_sel, last_sel_file, command=command)
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
def cmd_run(args: list[str]):
|
|
1544
|
+
"""wt run <work_name> <command>... - Run command in worktree and exit"""
|
|
1545
|
+
if len(args) < 2:
|
|
1546
|
+
print(msg("usage_run"), file=sys.stderr)
|
|
1547
|
+
sys.exit(1)
|
|
1548
|
+
|
|
1549
|
+
work_name = args[0]
|
|
1550
|
+
command = args[1:]
|
|
1551
|
+
|
|
1552
|
+
base_dir = find_base_dir()
|
|
1553
|
+
if not base_dir:
|
|
1554
|
+
print(msg("error", msg("base_not_found")), file=sys.stderr)
|
|
1555
|
+
sys.exit(1)
|
|
1556
|
+
|
|
1557
|
+
# find target path
|
|
1558
|
+
target_path = base_dir
|
|
1559
|
+
if work_name != "main":
|
|
1560
|
+
config = load_config(base_dir)
|
|
1561
|
+
worktrees_dir_name = config.get("worktrees_dir", ".worktrees")
|
|
1562
|
+
target_path = base_dir / worktrees_dir_name / work_name
|
|
1563
|
+
|
|
1564
|
+
if not target_path.exists():
|
|
1565
|
+
print(msg("error", msg("select_not_found", work_name)), file=sys.stderr)
|
|
1566
|
+
sys.exit(1)
|
|
1567
|
+
|
|
1568
|
+
# set environment variables
|
|
1569
|
+
env = os.environ.copy()
|
|
1570
|
+
env["WT_SESSION_NAME"] = work_name
|
|
1571
|
+
|
|
1572
|
+
# run command
|
|
1573
|
+
try:
|
|
1574
|
+
subprocess.run(command, cwd=target_path, env=env, check=True)
|
|
1575
|
+
except subprocess.CalledProcessError as e:
|
|
1576
|
+
sys.exit(e.returncode)
|
|
1577
|
+
except Exception as e:
|
|
1578
|
+
print(msg("error", str(e)), file=sys.stderr)
|
|
1579
|
+
sys.exit(1)
|
|
1522
1580
|
|
|
1523
1581
|
|
|
1524
1582
|
def cmd_current(args: list[str]):
|
|
@@ -1540,7 +1598,7 @@ def cmd_current(args: list[str]):
|
|
|
1540
1598
|
print(name)
|
|
1541
1599
|
|
|
1542
1600
|
|
|
1543
|
-
def switch_selection(target, base_dir, current_sel, last_sel_file):
|
|
1601
|
+
def switch_selection(target, base_dir, current_sel, last_sel_file, command: list[str] = None):
|
|
1544
1602
|
"""Switch selection and update last_selection"""
|
|
1545
1603
|
# Calculate target path
|
|
1546
1604
|
target_path = base_dir
|
|
@@ -1599,10 +1657,19 @@ def switch_selection(target, base_dir, current_sel, last_sel_file):
|
|
|
1599
1657
|
if os.environ.get("TMUX"):
|
|
1600
1658
|
subprocess.run(["tmux", "rename-window", f"wt:{target}"], check=False)
|
|
1601
1659
|
|
|
1602
|
-
|
|
1660
|
+
if command:
|
|
1661
|
+
cmd_str = " ".join(command)
|
|
1662
|
+
# コマンド実行後にシェルを維持するために "cmd; exec shell" を実行
|
|
1663
|
+
os.execl(shell, shell, "-c", f"{cmd_str}; exec {shell}")
|
|
1664
|
+
else:
|
|
1665
|
+
os.execl(shell, shell)
|
|
1603
1666
|
else:
|
|
1604
1667
|
# Output path for script/backtick use
|
|
1605
1668
|
print(str(target_path.absolute()))
|
|
1669
|
+
if command:
|
|
1670
|
+
# 非 TTY の場合でもコマンドがあれば実行しておく (パイプなどでの利用を想定)
|
|
1671
|
+
import subprocess
|
|
1672
|
+
subprocess.run(command, cwd=target_path, check=True)
|
|
1606
1673
|
|
|
1607
1674
|
|
|
1608
1675
|
def cmd_setup(args: list[str]):
|
|
@@ -1944,7 +2011,7 @@ def show_help():
|
|
|
1944
2011
|
|
|
1945
2012
|
def show_version():
|
|
1946
2013
|
"""Show version information"""
|
|
1947
|
-
print("easy-worktree version 0.1.
|
|
2014
|
+
print("easy-worktree version 0.1.7")
|
|
1948
2015
|
|
|
1949
2016
|
|
|
1950
2017
|
def main():
|
|
@@ -1991,6 +2058,8 @@ def main():
|
|
|
1991
2058
|
cmd_current(args)
|
|
1992
2059
|
elif command in ["co", "checkout"]:
|
|
1993
2060
|
cmd_checkout(args)
|
|
2061
|
+
elif command == "run":
|
|
2062
|
+
cmd_run(args)
|
|
1994
2063
|
else:
|
|
1995
2064
|
# その他のコマンドは git worktree にパススルー
|
|
1996
2065
|
cmd_passthrough([command] + args)
|
|
@@ -816,5 +816,28 @@ touch hook_ran.txt
|
|
|
816
816
|
expected_path = str((project_dir / ".worktrees" / "wt-select").absolute())
|
|
817
817
|
self.assertIn(expected_path, result.stdout.strip())
|
|
818
818
|
|
|
819
|
+
def test_22_run_command(self):
|
|
820
|
+
"""Test 'wt run <name> <cmd>'"""
|
|
821
|
+
project_dir = self.test_dir / "run-cmd-test"
|
|
822
|
+
if project_dir.exists():
|
|
823
|
+
shutil.rmtree(project_dir)
|
|
824
|
+
project_dir.mkdir()
|
|
825
|
+
subprocess.run(["git", "init"], cwd=project_dir)
|
|
826
|
+
(project_dir / "README.md").write_text("Hello")
|
|
827
|
+
subprocess.run(["git", "add", "."], cwd=project_dir)
|
|
828
|
+
subprocess.run(["git", "commit", "-m", "Initial commit"], cwd=project_dir)
|
|
829
|
+
self.run_wt(["init"], cwd=project_dir)
|
|
830
|
+
|
|
831
|
+
# Create a worktree
|
|
832
|
+
self.run_wt(["add", "wt-run"], cwd=project_dir)
|
|
833
|
+
|
|
834
|
+
# Run a command in it
|
|
835
|
+
# We'll touch a file and check its existence
|
|
836
|
+
result = self.run_wt(["run", "wt-run", "touch", "run_tested.txt"], cwd=project_dir)
|
|
837
|
+
self.assertEqual(result.returncode, 0)
|
|
838
|
+
|
|
839
|
+
wt_dir = project_dir / ".worktrees" / "wt-run"
|
|
840
|
+
self.assertTrue((wt_dir / "run_tested.txt").exists(), "Command 'touch' failed to create file in worktree")
|
|
841
|
+
|
|
819
842
|
if __name__ == "__main__":
|
|
820
843
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|