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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easy-worktree
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: Git worktree を簡単に管理するための CLI ツール
5
5
  Project-URL: Homepage, https://github.com/igtm/easy-worktree
6
6
  Project-URL: Repository, https://github.com/igtm/easy-worktree
@@ -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
- os.execl(shell, shell)
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.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)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "easy-worktree"
7
- version = "0.1.5"
7
+ version = "0.1.7"
8
8
  description = "Git worktree を簡単に管理するための CLI ツール"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -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()
@@ -4,7 +4,7 @@ requires-python = ">=3.10"
4
4
 
5
5
  [[package]]
6
6
  name = "easy-worktree"
7
- version = "0.1.4"
7
+ version = "0.1.6"
8
8
  source = { editable = "." }
9
9
  dependencies = [
10
10
  { name = "toml" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes