33
44import logging
55import os
6- from typing import Dict , List , Optional , Tuple , Any
6+ from typing import Dict , List , Optional , Tuple , Any , Union
77
88from k3handy import cmdf
99from k3handy import parse_flag
@@ -61,9 +61,9 @@ def repo_root(self, flag: str = "") -> Optional[str]:
6161 Examples:
6262 >>> git.repo_root()
6363 '/Users/user/project'
64- >>> git.repo_root(flag='x' ) # Raises if not in git repo
64+ >>> git.repo_root(flag=['raise'] ) # Raises if not in git repo
6565 """
66- return self .cmdf ("rev-parse" , "--show-toplevel" , flag = flag + "n0" )
66+ return self .cmdf ("rev-parse" , "--show-toplevel" , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
6767
6868 def repo_is_repository (self , path : Optional [str ] = None ) -> bool :
6969 """Check if path is a git repository.
@@ -92,15 +92,15 @@ def repo_is_repository(self, path: Optional[str] = None) -> bool:
9292
9393 # high level API
9494
95- def checkout (self , branch : str , flag : str = "x" ) -> Any :
95+ def checkout (self , branch : str , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> Any :
9696 """Checkout specified branch."""
9797 return self .cmdf ("checkout" , branch , flag = flag )
9898
9999 def fetch (self , name : str , flag : str = "" ) -> Any :
100100 """Fetch from remote repository."""
101101 return self .cmdf ("fetch" , name , flag = flag )
102102
103- def fetch_url (self , url : str , refspec : str , no_tags : bool = True , flag : str = "x" ) -> None :
103+ def fetch_url (self , url : str , refspec : str , no_tags : bool = True , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> None :
104104 """Fetch refspec from URL without adding remote.
105105
106106 Args:
@@ -132,7 +132,7 @@ def fetch_url(self, url: str, refspec: str, no_tags: bool = True, flag: str = "x
132132
133133 self .cmdf (* args , flag = flag )
134134
135- def add (self , * files : str , update : bool = False , flag : str = "x" ) -> Any :
135+ def add (self , * files : str , update : bool = False , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> Any :
136136 """Add files to staging area.
137137
138138 Args:
@@ -159,7 +159,7 @@ def add(self, *files: str, update: bool = False, flag: str = "x") -> Any:
159159
160160 return self .cmdf ("add" , * args , flag = flag )
161161
162- def commit (self , message , flag = "x" ):
162+ def commit (self , message , flag = [ "raise" ] ):
163163 """Commit staged changes with message.
164164
165165 Args:
@@ -170,9 +170,9 @@ def commit(self, message, flag="x"):
170170 str: Commit hash of new commit
171171 """
172172 self .cmdf ("commit" , "-m" , message , flag = flag )
173- return self .cmdf ("rev-parse" , "HEAD" , flag = flag + "n0" )
173+ return self .cmdf ("rev-parse" , "HEAD" , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
174174
175- def reset_to_commit (self , mode : str , target : Optional [str ] = None , flag : str = "x" ) -> Any :
175+ def reset_to_commit (self , mode : str , target : Optional [str ] = None , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> Any :
176176 """Reset HEAD to specified commit.
177177
178178 Args:
@@ -211,13 +211,15 @@ def worktree_staged_files(self, flag: str = "") -> List[str]:
211211 >>> git.worktree_staged_files()
212212 [] # Nothing staged
213213 """
214- return self .cmdf ("diff" , "--name-only" , "--cached" , flag = flag + "no" )
214+ return self .cmdf ("diff" , "--name-only" , "--cached" , flag = parse_flag ( flag , [ "none" , "stdout" ]) )
215215
216216 # branch
217217
218218 def branch_default_remote (self , branch : str , flag : str = "" ) -> Any :
219219 """Get default remote name for branch."""
220- return self .cmdf ("config" , "--get" , "branch.{}.remote" .format (branch ), flag = flag + "n0" )
220+ return self .cmdf (
221+ "config" , "--get" , "branch.{}.remote" .format (branch ), flag = parse_flag (flag , ["none" , "oneline" ])
222+ )
221223
222224 def branch_default_upstream (self , branch : str , flag : str = "" ) -> Any :
223225 """Get upstream branch name (e.g., origin/master for master)."""
@@ -226,10 +228,10 @@ def branch_default_upstream(self, branch: str, flag: str = "") -> Any:
226228 "--abbrev-ref" ,
227229 "--symbolic-full-name" ,
228230 branch + "@{upstream}" ,
229- flag = flag + "n0" ,
231+ flag = parse_flag ( flag , [ "none" , "oneline" ]) ,
230232 )
231233
232- def branch_set (self , branch : str , rev : str , flag : str = "x" ) -> None :
234+ def branch_set (self , branch : str , rev : str , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> None :
233235 """Set branch reference to specified revision."""
234236
235237 self .cmdf ("update-ref" , "refs/heads/{}" .format (branch ), rev , flag = flag )
@@ -251,7 +253,7 @@ def branch_list(self, scope: str = "local", flag: str = "") -> List[str]:
251253 def branch_common_base (self , branch : str , other : str , flag : str = "" ) -> Any :
252254 """Find merge base commit of two branches."""
253255
254- return self .cmdf ("merge-base" , branch , other , flag = flag + "0" )
256+ return self .cmdf ("merge-base" , branch , other , flag = parse_flag ( flag , [ "oneline" ]) )
255257
256258 def branch_divergency (self , branch : str , upstream : Optional [str ] = None , flag : str = "" ) -> Tuple [Any , Any , Any ]:
257259 """Get divergency between branch and upstream.
@@ -261,16 +263,16 @@ def branch_divergency(self, branch: str, upstream: Optional[str] = None, flag: s
261263 """
262264
263265 if upstream is None :
264- upstream = self .branch_default_upstream (branch , flag = "x" )
266+ upstream = self .branch_default_upstream (branch , flag = [ "raise" ] )
265267
266- base = self .branch_common_base (branch , upstream , flag = "x" )
268+ base = self .branch_common_base (branch , upstream , flag = [ "raise" ] )
267269
268- b_logs = self .cmdf ("log" , "--format=%H" , base + ".." + branch , flag = "xo" )
269- u_logs = self .cmdf ("log" , "--format=%H" , base + ".." + upstream , flag = "xo" )
270+ b_logs = self .cmdf ("log" , "--format=%H" , base + ".." + branch , flag = [ "raise" , "stdout" ] )
271+ u_logs = self .cmdf ("log" , "--format=%H" , base + ".." + upstream , flag = [ "raise" , "stdout" ] )
270272
271273 return (base , b_logs , u_logs )
272274
273- def branch_rebase (self , upstream : str , flag : str = "x" ) -> None :
275+ def branch_rebase (self , upstream : str , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> None :
274276 """Rebase current branch onto upstream.
275277
276278 Args:
@@ -290,7 +292,7 @@ def branch_rebase(self, upstream: str, flag: str = "x") -> None:
290292
291293 self .cmdf ("rebase" , upstream , flag = flag )
292294
293- def branch_merge_ff (self , upstream : Optional [str ] = None , flag : str = "x" ) -> None :
295+ def branch_merge_ff (self , upstream : Optional [str ] = None , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> None :
294296 """Fast-forward merge upstream into current branch.
295297
296298 Args:
@@ -318,19 +320,19 @@ def branch_merge_ff(self, upstream: Optional[str] = None, flag: str = "x") -> No
318320
319321 def head_branch (self , flag : str = "" ) -> Any :
320322 """Get current branch name."""
321- return self .cmdf ("symbolic-ref" , "--short" , "HEAD" , flag = flag + "n0" )
323+ return self .cmdf ("symbolic-ref" , "--short" , "HEAD" , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
322324
323325 # remote
324326
325327 def remote_get (self , name : str , flag : str = "" ) -> Any :
326328 """Get URL for remote."""
327- return self .cmdf ("remote" , "get-url" , name , flag = flag + "n0" )
329+ return self .cmdf ("remote" , "get-url" , name , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
328330
329- def remote_add (self , name : str , url : str , flag : str = "x" , ** options : Any ) -> None :
331+ def remote_add (self , name : str , url : str , flag : Union [ str , List [ str ]] = [ "raise" ] , ** options : Any ) -> None :
330332 """Add remote with name and URL."""
331333 self .cmdf ("remote" , "add" , name , url , ** options , flag = flag )
332334
333- def remote_push (self , remote : str , branch : str , flag : str = "x" ) -> None :
335+ def remote_push (self , remote : str , branch : str , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> None :
334336 """Push branch to remote.
335337
336338 Args:
@@ -353,7 +355,7 @@ def remote_push(self, remote: str, branch: str, flag: str = "x") -> None:
353355
354356 self .cmdf ("push" , remote , branch , flag = flag )
355357
356- def remote_push_all (self , branch : str , flag : str = "x" ) -> Dict [str , bool ]:
358+ def remote_push_all (self , branch : str , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> Dict [str , bool ]:
357359 """Push branch to all configured remotes.
358360
359361 Args:
@@ -371,24 +373,24 @@ def remote_push_all(self, branch: str, flag: str = "x") -> Dict[str, bool]:
371373
372374 Raises:
373375 ValueError: If branch is empty
374- CalledProcessError: If flag='x' and any push fails
376+ CalledProcessError: If flag=['raise'] and any push fails
375377 """
376378 if not branch :
377379 raise ValueError ("branch cannot be empty" )
378380
379381 # Get all remotes
380382 from k3handy import CalledProcessError
381383
382- remotes_output = self .cmdf ("remote" , flag = "xo" )
384+ remotes_output = self .cmdf ("remote" , flag = [ "raise" , "stdout" ] )
383385 results = {}
384386
385387 for remote in remotes_output :
386388 try :
387- self .remote_push (remote , branch , flag = "x" )
389+ self .remote_push (remote , branch , flag = [ "raise" ] )
388390 results [remote ] = True
389391 except CalledProcessError :
390392 results [remote ] = False
391- if "x " in flag :
393+ if "raise " in parse_flag ( flag ) :
392394 raise
393395
394396 return results
@@ -397,35 +399,37 @@ def remote_push_all(self, branch: str, flag: str = "x") -> Dict[str, bool]:
397399
398400 def blob_new (self , f : str , flag : str = "" ) -> Any :
399401 """Create new blob from file."""
400- return self .cmdf ("hash-object" , "-w" , f , flag = flag + "n0" )
402+ return self .cmdf ("hash-object" , "-w" , f , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
401403
402404 # tree
403405
404406 def tree_of (self , commit : str , flag : str = "" ) -> Any :
405407 """Get tree hash of commit."""
406- return self .cmdf ("rev-parse" , commit + "^{tree}" , flag = flag + "n0" )
408+ return self .cmdf ("rev-parse" , commit + "^{tree}" , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
407409
408410 def tree_commit (
409411 self ,
410412 treeish : str ,
411413 commit_message : str ,
412414 parent_commits : List [str ],
413- flag : str = "x" ,
415+ flag : Union [ str , List [ str ]] = [ "raise" ] ,
414416 ) -> Any :
415417 """Create commit from tree with message and parents."""
416418
417419 parent_args = []
418420 for c in parent_commits :
419421 parent_args .extend (["-p" , c ])
420422
421- return self .cmdf ("commit-tree" , treeish , * parent_args , input = commit_message , flag = flag + "n0" )
423+ return self .cmdf (
424+ "commit-tree" , treeish , * parent_args , input = commit_message , flag = parse_flag (flag , ["none" , "oneline" ])
425+ )
422426
423427 def tree_items (
424428 self ,
425429 treeish : str ,
426430 name_only : bool = False ,
427431 with_size : bool = False ,
428- flag : str = "x" ,
432+ flag : Union [ str , List [ str ]] = [ "raise" ] ,
429433 ) -> Any :
430434 """List items in tree."""
431435 args = []
@@ -434,7 +438,7 @@ def tree_items(
434438
435439 if with_size :
436440 args .append ("--long" )
437- return self .cmdf ("ls-tree" , treeish , * args , flag = flag + "no" )
441+ return self .cmdf ("ls-tree" , treeish , * args , flag = parse_flag ( flag , [ "none" , "stdout" ]) )
438442
439443 def tree_add_obj (self , cur_tree : str , path : str , treeish : str ) -> Any :
440444 """Add object to tree at specified path."""
@@ -444,7 +448,7 @@ def tree_add_obj(self, cur_tree: str, path: str, treeish: str) -> Any:
444448 itms = self .tree_items (cur_tree )
445449
446450 if sep not in path :
447- return self .tree_new_replace (itms , path , treeish , flag = "x" )
451+ return self .tree_new_replace (itms , path , treeish , flag = [ "raise" ] )
448452
449453 # a/b/c -> a, b/c
450454 p0 , left = path .split (sep , 1 )
@@ -453,12 +457,12 @@ def tree_add_obj(self, cur_tree: str, path: str, treeish: str) -> Any:
453457 if p0item is None :
454458 newsubtree = treeish
455459 for p in reversed (left .split (sep )):
456- newsubtree = self .tree_new_replace ([], p , newsubtree , flag = "x" )
460+ newsubtree = self .tree_new_replace ([], p , newsubtree , flag = [ "raise" ] )
457461 else :
458462 subtree = p0item ["object" ]
459463 newsubtree = self .tree_add_obj (subtree , left , treeish )
460464
461- return self .tree_new_replace (itms , p0 , newsubtree , flag = "x" )
465+ return self .tree_new_replace (itms , p0 , newsubtree , flag = [ "raise" ] )
462466
463467 def tree_find_item (
464468 self , treeish : str , fn : Optional [str ] = None , typ : Optional [str ] = None
@@ -505,10 +509,10 @@ def treeitem_parse(self, line: str) -> Dict[str, str]:
505509
506510 return rst
507511
508- def tree_new (self , itms : List [str ], flag : str = "x" ) -> Any :
512+ def tree_new (self , itms : List [str ], flag : Union [ str , List [ str ]] = [ "raise" ] ) -> Any :
509513 """Create new tree from items."""
510514
511- treeish = self .cmdf ("mktree" , input = "\n " .join (itms ), flag = flag + "n0" )
515+ treeish = self .cmdf ("mktree" , input = "\n " .join (itms ), flag = parse_flag ( flag , [ "none" , "oneline" ]) )
512516 return treeish
513517
514518 def tree_new_replace (
@@ -517,13 +521,13 @@ def tree_new_replace(
517521 name : str ,
518522 obj : str ,
519523 mode : Optional [str ] = None ,
520- flag : str = "x" ,
524+ flag : Union [ str , List [ str ]] = [ "raise" ] ,
521525 ) -> Any :
522526 """Create new tree replacing/adding item."""
523527
524528 new_items = self .treeitems_replace_item (itms , name , obj , mode = mode )
525529
526- new_treeish = self .cmdf ("mktree" , input = "\n " .join (new_items ), flag = flag + "n0" )
530+ new_treeish = self .cmdf ("mktree" , input = "\n " .join (new_items ), flag = parse_flag ( flag , [ "none" , "oneline" ]) )
527531 return new_treeish
528532
529533 def treeitems_replace_item (
@@ -544,7 +548,7 @@ def treeitems_replace_item(
544548 def treeitem_new (self , name : str , obj : str , mode : Optional [str ] = None ) -> str :
545549 """Create new tree item string."""
546550
547- typ = self .obj_type (obj , flag = "x" )
551+ typ = self .obj_type (obj , flag = [ "raise" ] )
548552 item_fmt = "{mode} {typ} {object}\t {name}"
549553
550554 if typ == "tree" :
@@ -578,7 +582,7 @@ def ref_list(self, flag: str = "") -> Dict[str, str]:
578582 # 104403398142d4643669be8099697a6b51bbbc62 refs/remotes/origin/master
579583 # 4a90cdaec2e7bb945c9a49148919db0a6ffa059d refs/tags/v0.1.0
580584 # b1af433f3291ff137679ad3889be5d72377f0cb6 refs/tags/v0.1.10
581- hash_and_refs = self .cmdf ("show-ref" , flag = parse_flag ("xo" , flag ))
585+ hash_and_refs = self .cmdf ("show-ref" , flag = parse_flag ([ "raise" , "stdout" ] , flag ))
582586
583587 res = {}
584588 for line in hash_and_refs :
@@ -588,7 +592,7 @@ def ref_list(self, flag: str = "") -> Dict[str, str]:
588592
589593 return res
590594
591- def ref_delete (self , ref : str , flag : str = "x" ) -> None :
595+ def ref_delete (self , ref : str , flag : Union [ str , List [ str ]] = [ "raise" ] ) -> None :
592596 """Delete a git reference.
593597
594598 Args:
@@ -620,11 +624,11 @@ def rev_of(self, name: str, flag: str = "") -> Optional[str]:
620624 Returns:
621625 str: SHA hash or None if not found
622626 """
623- return self .cmdf ("rev-parse" , "--verify" , "--quiet" , name , flag = flag + "n0" )
627+ return self .cmdf ("rev-parse" , "--verify" , "--quiet" , name , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
624628
625629 def obj_type (self , obj : str , flag : str = "" ) -> Any :
626630 """Get object type (blob, tree, commit, tag)."""
627- return self .cmdf ("cat-file" , "-t" , obj , flag = flag + "n0" )
631+ return self .cmdf ("cat-file" , "-t" , obj , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
628632
629633 # log
630634
@@ -658,7 +662,7 @@ def log_date(self, ref: str, format: str = "%ad", flag: str = "") -> Optional[st
658662 if not ref :
659663 raise ValueError ("ref cannot be empty" )
660664
661- return self .cmdf ("log" , "-1" , "--format=" + format , ref , flag = flag + "n0" )
665+ return self .cmdf ("log" , "-1" , "--format=" + format , ref , flag = parse_flag ( flag , [ "none" , "oneline" ]) )
662666
663667 def log_grep (
664668 self ,
@@ -701,7 +705,7 @@ def log_grep(
701705 raise ValueError ("max_count must be >= 1" )
702706 args .append (f"--max-count={ max_count } " )
703707
704- return self .cmdf (* args , flag = flag + "no" )
708+ return self .cmdf (* args , flag = parse_flag ( flag , [ "none" , "stdout" ]) )
705709
706710 # wrapper of cli
707711
0 commit comments