Skip to content

Conversation

@tony
Copy link
Member

@tony tony commented Jun 18, 2024

Changes

Commands (git)

This PR introduces the Manager/Cmd pattern for git subcommands, providing typed Python objects instead of raw strings.

Pattern Overview

Manager (collection-level)              Cmd (per-entity)
├── ls() -> QueryList[Cmd]              ├── run()
├── get(**kwargs) -> Cmd                ├── show()
├── filter(**kwargs) -> list[Cmd]       ├── remove()/delete()
├── add() / create()                    └── entity-specific operations
└── run()

Add GitBranchManager (git.branches) - collection-level branch operations

  • ls() - List branches, returns QueryList[GitBranchCmd]
    • _all - List all branches (local + remote)
    • remotes - List remote branches only
    • merged / no_merged - Filter by merge status
    • contains - Branches containing commit
    • verbose - Show tracking info
  • get(**kwargs) - Get single branch by filter
  • filter(**kwargs) - Filter branches
  • checkout(branch) - Checkout a branch
  • create(branch) - Create new branch via checkout -b

Add GitBranchCmd (git.branches.get(...)) - instance-based mutations of a branch

  • checkout() - git checkout <branchname>
  • create() - git checkout -b <branchname>
  • delete(force) - git branch -d / -D
  • rename(new_name, force) - git branch -m / -M
  • copy(new_name, force) - git branch -c / -C
  • set_upstream(upstream) - git branch --set-upstream-to
  • unset_upstream() - git branch --unset-upstream
  • track(remote_branch) - git branch -t

Add GitRemoteManager (git.remotes) - collection-level remote operations

  • ls() - List remotes, returns QueryList[GitRemoteCmd]
  • get(**kwargs) - Get single remote by filter
  • filter(**kwargs) - Filter remotes
  • add(name, url, ...) - Add new remote
  • show(name, verbose) - Show remotes

Enhance GitRemoteCmd (git.remotes.get(...)) - instance-based remote operations

  • rename(new_name, progress) - Rename remote
  • remove() - Delete remote
  • show(verbose, no_query_remotes) - Show remote details
  • prune(dry_run) - Prune stale branches
  • get_url(push, _all) - Get remote URL
  • set_url(url, push, add, delete) - Set remote URL
  • set_branches(*branches, add) - Set tracked branches
  • set_head(branch, auto, delete) - Set HEAD reference
  • update(prune) - Update remote

Add GitStashManager (git.stashes) - collection-level stash operations

  • ls() - List stashes, returns QueryList[GitStashEntryCmd]
  • get(**kwargs) - Get single stash by filter
  • filter(**kwargs) - Filter stashes
  • push(message, path, patch, staged, ...) - Push to stash
  • clear() - Clear all stashes

Add GitStashEntryCmd (git.stashes.get(...)) - instance-based stash operations

  • show(stat, patch) - Show stash diff
  • apply(index) - Apply without removing
  • pop(index) - Apply and remove
  • drop() - Delete this stash
  • branch(branch_name) - Create branch from stash

Add GitTagManager (git.tags) - collection-level tag operations

  • ls(pattern, sort, contains, merged, ...) - List tags, returns QueryList[GitTagCmd]
  • get(**kwargs) - Get single tag by filter
  • filter(**kwargs) - Filter tags
  • create(name, ref, message, annotate, sign, force) - Create tag

Add GitTagCmd (git.tags.get(...)) - instance-based tag operations

  • show() - Show tag details
  • delete() - Delete tag
  • verify() - Verify signed tag

Add GitWorktreeManager (git.worktrees) - collection-level worktree operations

  • ls() - List worktrees, returns QueryList[GitWorktreeCmd]
  • get(**kwargs) - Get single worktree by filter
  • filter(**kwargs) - Filter worktrees
  • add(path, branch, detach, checkout, lock, force) - Add worktree
  • prune(dry_run, verbose, expire) - Prune worktrees

Add GitWorktreeCmd (git.worktrees.get(...)) - instance-based worktree operations

  • remove(force) - Remove worktree
  • lock(reason) - Lock worktree
  • unlock() - Unlock worktree
  • move(new_path) - Move worktree
  • repair() - Repair worktree

Add GitNotesManager (git.notes) - collection-level notes operations

  • ls(ref) - List notes, returns QueryList[GitNoteCmd]
  • get(**kwargs) - Get single note by filter
  • filter(**kwargs) - Filter notes
  • add(object, message, file, force, allow_empty) - Add note
  • prune(dry_run, verbose) - Prune notes
  • merge(notes_ref, strategy, commit, abort, quiet) - Merge notes
  • get_ref() - Get notes ref

Add GitNoteCmd (git.notes.get(...)) - instance-based note operations

  • show() - Show note
  • append(message) - Append to note
  • copy(from_object) - Copy note
  • remove() - Remove note

Add GitSubmoduleManager (git.submodules) - collection-level submodule operations

  • ls() - List submodules, returns QueryList[GitSubmoduleEntryCmd]
  • get(**kwargs) - Get single submodule by filter
  • filter(**kwargs) - Filter submodules
  • add(url, path, branch, name, force) - Add submodule
  • foreach(command, recursive) - Execute in each submodule
  • sync(recursive) - Sync submodule URLs
  • summary(commit, files, cached) - Summarize changes

Add GitSubmoduleEntryCmd (git.submodules.get(...)) - instance-based submodule operations

  • init() - Initialize this submodule
  • update(init, force, checkout, rebase, merge, recursive) - Update
  • deinit(force) - Unregister submodule
  • set_branch(branch) - Set branch
  • set_url(url) - Set URL
  • status() - Show status
  • absorbgitdirs() - Absorb gitdir

Add GitReflogManager (git.reflog) - collection-level reflog operations

  • ls(ref) - List reflog entries, returns QueryList[GitReflogEntryCmd]
  • get(**kwargs) - Get single entry by filter
  • filter(**kwargs) - Filter entries
  • expire(ref, _all, dry_run, rewrite, ...) - Expire entries
  • exists(ref) - Check if reflog exists

Add GitReflogEntryCmd (git.reflog.get(...)) - instance-based reflog operations

  • show() - Show entry details
  • delete(rewrite, updateref) - Delete entry

Enhance Git.init() - additional parameters and validation

  • ref_format - --ref-format (files/reftable)
  • make_parents - Auto-create parent directories (default: True)
  • shared - Extended to support octal permissions (e.g., "0660")
  • Improved parameter validation with clear error messages

@codecov
Copy link

codecov bot commented Jun 18, 2024

Codecov Report

❌ Patch coverage is 99.49367% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.77%. Comparing base (4e29246) to head (4e3ca5f).

Files with missing lines Patch % Lines
tests/cmd/test_git.py 99.48% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #465      +/-   ##
==========================================
+ Coverage   42.90%   51.77%   +8.86%     
==========================================
  Files          38       38              
  Lines        3627     5451    +1824     
  Branches      794     1037     +243     
==========================================
+ Hits         1556     2822    +1266     
- Misses       1718     2104     +386     
- Partials      353      525     +172     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tony tony force-pushed the more-git-cmds branch 3 times, most recently from ff046f3 to 5dff81e Compare June 24, 2024 00:02
@tony tony force-pushed the more-git-cmds branch 8 times, most recently from 8808231 to 700a4fa Compare July 4, 2024 23:01
@tony tony force-pushed the more-git-cmds branch 3 times, most recently from f520132 to af58b49 Compare July 20, 2024 11:39
@tony tony force-pushed the more-git-cmds branch 2 times, most recently from adfbeaa to 76822c5 Compare August 3, 2024 12:20
@tony tony force-pushed the more-git-cmds branch 4 times, most recently from 8adff4c to c843022 Compare August 10, 2024 19:57
@tony tony force-pushed the more-git-cmds branch 3 times, most recently from 8839c2a to 0385215 Compare August 16, 2024 23:56
@tony tony force-pushed the more-git-cmds branch 2 times, most recently from 11dbd6a to 8578585 Compare August 26, 2024 10:50
@tony tony force-pushed the more-git-cmds branch 4 times, most recently from 2e5347d to bb6d40e Compare September 6, 2024 23:56
tony added 6 commits November 26, 2025 17:42
…tryCmd classes

why: Enable reflog management with Manager/Cmd pattern for consistency
what:
- Add GitReflogEntry dataclass for structured reflog data
- Add GitReflogEntryCmd for per-entry operations (show, delete)
- Add GitReflogManager for collection operations (show, expire, exists)
- Support QueryList-based filtering with ls(), get(), filter() methods
- Parse `git reflog show` output into GitReflogEntry objects
- Add self.reflog to Git class for easy access via git.reflog
- Include comprehensive doctests for all methods
why: Ensure GitReflogManager and GitReflogEntryCmd work correctly
what:
- Add ReflogShowFixture with parametrized tests for show operation
- Add tests for ls, get, filter, exists, expire operations
- Add test for GitReflogEntryCmd.show via entry.cmd
- All 8 tests verify core reflog functionality
…bmoduleEntryCmd

why: Complete the Manager/Cmd pattern for submodule operations
what:
- Add GitSubmodule dataclass with name, path, url, sha, branch, status_prefix
- Add GitSubmoduleEntryCmd for per-submodule operations: init, update, deinit,
  set_branch, set_url, status, absorbgitdirs
- Add GitSubmoduleManager with collection operations: add, init, update, foreach,
  sync, summary, absorbgitdirs, _ls, ls, get, filter
- Add 'add' to GitSubmoduleCmdCommandLiteral
- Add self.submodules to Git class for easy access
- Fix return type assertions in get() methods for mypy
why: Validate GitSubmoduleManager and GitSubmoduleEntryCmd functionality
what:
- Add submodule_repo fixture for creating submodule source repos
- Add _setup_submodule_test helper to configure file protocol
- Test GitSubmoduleManager methods: add, ls, get, filter, init, update,
  sync, summary, foreach
- Test GitSubmoduleEntryCmd methods: status, init, update
- Test GitSubmodule dataclass properties
- Test ObjectDoesNotExist raised when submodule not found
… run()

why: The doctest for GitNoteCmd.edit hung because:
1. git notes edit opens an interactive editor
2. GitNoteCmd.run() wasn't passing **kwargs to self.cmd.run()
   so config={'core.editor': 'true'} was being dropped

what:
- Use config={'core.editor': 'true'} to override editor via -c flag
- Pass **kwargs through GitNoteCmd.run() to self.cmd.run()
why: Fix ruff SIM108 lint error
what:
- Convert if/else to ternary operator for stash apply/pop
tony added 2 commits November 26, 2025 17:47
why: The doctest used https://github.com/example/repo.git which prompts
for GitHub credentials, causing the test to hang.
what:
- Use create_git_remote_repo() fixture with file:// URL
- Matches pattern used by GitRemoteManager.add
why: CI failed because git returns "unchanged" when HEAD is already set,
but assertion only checked for "set to".
what:
- Add "unchanged" as valid response in set_head auto assertion
tony added 4 commits November 27, 2025 03:58
why: The docstring had a TODO placeholder instead of proper documentation.
what:
- Add proper description for push method
- Document path, patch, and staged parameters
- Add link to git-stash documentation
why: Complete branch management API per planning docs
what:
- Add GitBranchCmd.track() to create branches tracking remote refs
- Add filter params to GitBranchManager.ls(): _all, remotes, merged,
  no_merged, contains, sort
- Update _ls() to accept local_flags parameter
why: Verify new branch management functionality
what:
- Add test_branch_track() for GitBranchCmd.track()
- Add test_branch_ls_filters() for ls() filter parameters
why: Doctests failed due to state pollution - tags from earlier doctests
affected later tests; use ELLIPSIS for cleaner pattern matching
what:
- GitTagCmd.run: create tag, verify with '...test-tag...'
- GitTagManager.__init__: create tag, verify with '...init-doctest-tag...'
- GitTagManager.run: create tag, verify with '...run-doctest-tag...'
tony added 2 commits November 27, 2025 08:51
why: Complete GitBranchManager.ls() filter options to match GitTagManager.ls()
what:
- Add verbose: bool parameter to ls() method
- Add helper function to extract branch name from verbose output
- Verbose output format is "name  sha1 message" - parse correctly
why: Test the verbose parameter added to GitBranchManager.ls()
what:
- Verify verbose=True returns branch names correctly
- Check that verbose output parsing extracts names properly
tony added 2 commits November 27, 2025 09:27
why: Complete test coverage for implemented methods lacking unit tests
what:
- Add test_worktree_move and test_worktree_repair for GitWorktreeCmd
- Add test_notes_edit, test_notes_copy, test_notes_merge for GitNoteCmd
- Add test_submodule_entry_deinit, test_submodule_entry_set_branch,
  test_submodule_entry_set_url, test_submodule_entry_absorbgitdirs
- Add test_reflog_entry_delete for GitReflogEntryCmd
why: Reflect actual implementation status in planning document
what:
- Update GitBranchCmd methods (delete, rename, copy, etc.) to Implemented
- Update GitBranchManager enhancements to Implemented
- Update GitRemoteCmd methods (set_branches, set_head, update) to Implemented
- Update all Manager/Cmd classes to Implemented status
why: New git subcommand classes (branch, tag, worktree, notes, reflog) and
Manager pattern classes need API documentation for discoverability.
what:
- Add new doc files: branch.md, tag.md, worktree.md, notes.md, reflog.md
- Update remote.md, stash.md, submodule.md to include Manager classes
- Update index.md toctree and exclude-members for all 19 new classes
tony added 7 commits November 27, 2025 10:14
why: Document major new features for the upcoming release.
what:
- Add Manager/Cmd pattern for git subcommands (branches, remotes, stashes, tags, worktrees, notes, submodules, reflog)
- Document enhanced Git.init() with new parameters
- Note documentation and test additions
why: Help users understand the new architecture for git subcommands.
what:
- Add pattern overview with Manager vs Cmd explanation
- Add tree diagram showing all available managers
- Add quick example showing common operations
why: Showcase the new typed Python API for git subcommands.
what:
- Add "Manage Branches, Tags, and More" section
- Show examples for branches, tags, and remotes
- Link to full Manager/Cmd documentation
why: Provide getting-started examples beyond installation.
what:
- Add Commands section with git init/clone/status examples
- Add Subcommand Managers section with branches/tags/remotes
- Link to full API reference
why: Help users understand the cmd module and when to use it.
what:
- Add overview with links to git, hg, svn modules
- Add comparison table for cmd vs sync use cases
why: Make Manager/Cmd pattern usage clear at a glance
what:
- Add Overview section with pattern explanation to all 8 pages
- Include practical code examples for each subcommand
- Reference git man pages (e.g., git-branch(1))
- Note legacy interfaces where applicable (stash, submodule)
why: Show how QueryList powers the Manager/Cmd pattern
what:
- Add overview explaining ls() returns QueryList
- Document all available lookup operators
- Show filter chaining examples
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants