<s> from os import unlink <EOL> from tempfile import mkstemp <EOL> from functools import partial <EOL> from contextlib import contextmanager <EOL> from collections import namedtuple <EOL> import git <EOL> from git . exc import GitCommandError , BadObject <EOL> from jig . exc import ( <EOL> GitRevListFormatError , GitRevListMissing , GitWorkingDirectoryDirty , <EOL> TrackingBranchMissing ) <EOL> from jig . gitutils . checks import working_directory_dirty <EOL> def parse_rev_range ( repository , rev_range ) : <EOL> """<STR_LIT>""" <EOL> rev_pair = rev_range . split ( '<STR_LIT:..>' ) <EOL> if len ( rev_pair ) != <NUM_LIT:2> or not all ( rev_pair ) : <EOL> raise GitRevListFormatError ( rev_range ) <EOL> rev_a , rev_b = rev_pair <EOL> try : <EOL> repo = git . Repo ( repository ) <EOL> commit_a = repo . commit ( rev_a ) <EOL> commit_b = repo . commit ( rev_b ) <EOL> return RevRangePair ( commit_a , commit_b , rev_range ) <EOL> except ( BadObject , GitCommandError ) : <EOL> raise GitRevListMissing ( rev_range ) <EOL> @ contextmanager <EOL> def _prepare_with_rev_range ( repo , rev_range ) : <EOL> if rev_range and working_directory_dirty ( repo . working_dir ) : <EOL> raise GitWorkingDirectoryDirty ( ) <EOL> try : <EOL> head = repo . head . reference <EOL> return_to_normal = head . checkout <EOL> except TypeError : <EOL> head = repo . head . commit <EOL> return_to_normal = partial ( repo . git . checkout , head . hexsha ) <EOL> repo . git . checkout ( rev_range . b . hexsha ) <EOL> try : <EOL> yield head <EOL> finally : <EOL> return_to_normal ( ) <EOL> @ contextmanager <EOL> def _prepare_against_staged_index ( repo ) : <EOL> """<STR_LIT>""" <EOL> stash = None <EOL> if repo . is_dirty ( index = False , working_tree = True , untracked_files = False ) : <EOL> stash = repo . git . stash ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> try : <EOL> yield stash <EOL> finally : <EOL> if not stash : <EOL> return <EOL> os_handle , patchfile = mkstemp ( ) <EOL> with open ( patchfile , '<STR_LIT:w>' ) as fh : <EOL> repo . git . diff ( <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> output_stream = fh ) <EOL> repo . git . apply ( patchfile ) <EOL> unlink ( patchfile ) <EOL> repo . git . stash ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> @ contextmanager <EOL> def prepare_working_directory ( repository , rev_range = None ) : <EOL> """<STR_LIT>""" <EOL> repo = git . Repo ( repository ) <EOL> if rev_range : <EOL> with _prepare_with_rev_range ( repo , rev_range ) as head : <EOL> yield head <EOL> else : <EOL> with _prepare_against_staged_index ( repo ) as stash : <EOL> yield stash <EOL> RevRangePair = namedtuple ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> class Tracked ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , gitrepo , tracking_branch = '<STR_LIT>' ) : <EOL> self . gitrepo = git . Repo ( gitrepo ) <EOL> self . tracking_branch = tracking_branch <EOL> @ property <EOL> def exists ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . tracking_branch in self . gitrepo . references <EOL> def _create ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . gitrepo . create_head ( self . tracking_branch ) <EOL> @ property <EOL> def reference ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . exists : <EOL> raise TrackingBranchMissing ( self . tracking_branch ) <EOL> return self . gitrepo . references [ self . tracking_branch ] <EOL> def update ( self , commit = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> reference = self . reference if self . exists else self . _create ( ) <EOL> reference . commit = commit <EOL> return reference </s>
