<s> import re <EOL> from itertools import chain <EOL> from dulwich import objects <EOL> from subprocess import Popen , PIPE <EOL> from vcs . conf import settings <EOL> from vcs . backends . base import BaseChangeset , EmptyChangeset <EOL> from vcs . exceptions import ( <EOL> RepositoryError , ChangesetError , NodeDoesNotExistError , VCSError , <EOL> ChangesetDoesNotExistError , ImproperArchiveTypeError <EOL> ) <EOL> from vcs . nodes import ( <EOL> FileNode , DirNode , NodeKind , RootNode , SubModuleNode , <EOL> ChangedFileNodesGenerator , AddedFileNodesGenerator , RemovedFileNodesGenerator <EOL> ) <EOL> from vcs . utils import ( <EOL> safe_unicode , safe_str , safe_int , date_fromtimestamp <EOL> ) <EOL> from vcs . utils . lazy import LazyProperty <EOL> class GitChangeset ( BaseChangeset ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , repository , revision ) : <EOL> self . _stat_modes = { } <EOL> self . repository = repository <EOL> try : <EOL> commit = self . repository . _repo [ revision ] <EOL> if isinstance ( commit , objects . Tag ) : <EOL> revision = commit . object [ <NUM_LIT:1> ] <EOL> commit = self . repository . _repo . get_object ( commit . object [ <NUM_LIT:1> ] ) <EOL> except KeyError : <EOL> raise RepositoryError ( "<STR_LIT>" % revision ) <EOL> self . raw_id = revision <EOL> self . id = self . raw_id <EOL> self . short_id = self . raw_id [ : <NUM_LIT:12> ] <EOL> self . _commit = commit <EOL> self . _tree_id = commit . tree <EOL> self . _committer_property = '<STR_LIT>' <EOL> self . _author_property = '<STR_LIT>' <EOL> self . _date_property = '<STR_LIT>' <EOL> self . _date_tz_property = '<STR_LIT>' <EOL> self . revision = repository . revisions . index ( revision ) <EOL> self . nodes = { } <EOL> self . _paths = { } <EOL> @ LazyProperty <EOL> def message ( self ) : <EOL> return safe_unicode ( self . _commit . message ) <EOL> @ LazyProperty <EOL> def committer ( self ) : <EOL> return safe_unicode ( getattr ( self . _commit , self . _committer_property ) ) <EOL> @ LazyProperty <EOL> def author ( self ) : <EOL> return safe_unicode ( getattr ( self . _commit , self . _author_property ) ) <EOL> @ LazyProperty <EOL> def date ( self ) : <EOL> return date_fromtimestamp ( getattr ( self . _commit , self . _date_property ) , <EOL> getattr ( self . _commit , self . _date_tz_property ) ) <EOL> @ LazyProperty <EOL> def _timestamp ( self ) : <EOL> return getattr ( self . _commit , self . _date_property ) <EOL> @ LazyProperty <EOL> def status ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . changed , self . added , self . removed <EOL> @ LazyProperty <EOL> def tags ( self ) : <EOL> _tags = [ ] <EOL> for tname , tsha in self . repository . tags . iteritems ( ) : <EOL> if tsha == self . raw_id : <EOL> _tags . append ( tname ) <EOL> return _tags <EOL> @ LazyProperty <EOL> def branch ( self ) : <EOL> heads = self . repository . _heads ( reverse = False ) <EOL> ref = heads . get ( self . raw_id ) <EOL> if ref : <EOL> return safe_unicode ( ref ) <EOL> def _fix_path ( self , path ) : <EOL> """<STR_LIT>""" <EOL> if path . endswith ( '<STR_LIT:/>' ) : <EOL> path = path . rstrip ( '<STR_LIT:/>' ) <EOL> return path <EOL> def _get_id_for_path ( self , path ) : <EOL> if not path in self . _paths : <EOL> path = path . strip ( '<STR_LIT:/>' ) <EOL> tree = self . repository . _repo [ self . _tree_id ] <EOL> if path == '<STR_LIT>' : <EOL> self . _paths [ '<STR_LIT>' ] = tree . id <EOL> return tree . id <EOL> splitted = path . split ( '<STR_LIT:/>' ) <EOL> dirs , name = splitted [ : - <NUM_LIT:1> ] , splitted [ - <NUM_LIT:1> ] <EOL> curdir = '<STR_LIT>' <EOL> for item , stat , id in tree . iteritems ( ) : <EOL> if curdir : <EOL> name = '<STR_LIT:/>' . join ( ( curdir , item ) ) <EOL> else : <EOL> name = item <EOL> self . _paths [ name ] = id <EOL> self . _stat_modes [ name ] = stat <EOL> for dir in dirs : <EOL> if curdir : <EOL> curdir = '<STR_LIT:/>' . join ( ( curdir , dir ) ) <EOL> else : <EOL> curdir = dir <EOL> dir_id = None <EOL> for item , stat , id in tree . iteritems ( ) : <EOL> if dir == item : <EOL> dir_id = id <EOL> if dir_id : <EOL> tree = self . repository . _repo [ dir_id ] <EOL> if not isinstance ( tree , objects . Tree ) : <EOL> raise ChangesetError ( '<STR_LIT>' % curdir ) <EOL> else : <EOL> raise ChangesetError ( '<STR_LIT>' % curdir ) <EOL> for item , stat , id in tree . iteritems ( ) : <EOL> if curdir : <EOL> name = '<STR_LIT:/>' . join ( ( curdir , item ) ) <EOL> else : <EOL> name = item <EOL> self . _paths [ name ] = id <EOL> self . _stat_modes [ name ] = stat <EOL> if not path in self . _paths : <EOL> raise NodeDoesNotExistError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> % ( path , self . short_id ) ) <EOL> return self . _paths [ path ] <EOL> def _get_kind ( self , path ) : <EOL> obj = self . repository . _repo [ self . _get_id_for_path ( path ) ] <EOL> if isinstance ( obj , objects . Blob ) : <EOL> return NodeKind . FILE <EOL> elif isinstance ( obj , objects . Tree ) : <EOL> return NodeKind . DIR <EOL> def _get_filectx ( self , path ) : <EOL> path = self . _fix_path ( path ) <EOL> if self . _get_kind ( path ) != NodeKind . FILE : <EOL> raise ChangesetError ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( self . raw_id , path ) ) <EOL> return path <EOL> def _get_file_nodes ( self ) : <EOL> return chain ( * ( t [ <NUM_LIT:2> ] for t in self . walk ( ) ) ) <EOL> @ LazyProperty <EOL> def parents ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ self . repository . get_changeset ( parent ) <EOL> for parent in self . _commit . parents ] <EOL> @ LazyProperty <EOL> def children ( self ) : <EOL> """<STR_LIT>""" <EOL> rev_filter = settings . GIT_REV_FILTER <EOL> cmd = "<STR_LIT>" % ( rev_filter , self . raw_id ) <EOL> so , se = self . repository . run_git_command ( cmd ) <EOL> children = [ ] <EOL> for l in so . splitlines ( ) : <EOL> childs = l . split ( '<STR_LIT:U+0020>' ) [ <NUM_LIT:1> : ] <EOL> children . extend ( childs ) <EOL> return [ self . repository . get_changeset ( cs ) for cs in children ] <EOL> def next ( self , branch = None ) : <EOL> if branch and self . branch != branch : <EOL> raise VCSError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> def _next ( changeset , branch ) : <EOL> try : <EOL> next_ = changeset . revision + <NUM_LIT:1> <EOL> next_rev = changeset . repository . revisions [ next_ ] <EOL> except IndexError : <EOL> raise ChangesetDoesNotExistError <EOL> cs = changeset . repository . get_changeset ( next_rev ) <EOL> if branch and branch != cs . branch : <EOL> return _next ( cs , branch ) <EOL> return cs <EOL> return _next ( self , branch ) <EOL> def prev ( self , branch = None ) : <EOL> if branch and self . branch != branch : <EOL> raise VCSError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> def _prev ( changeset , branch ) : <EOL> try : <EOL> prev_ = changeset . revision - <NUM_LIT:1> <EOL> if prev_ < <NUM_LIT:0> : <EOL> raise IndexError <EOL> prev_rev = changeset . repository . revisions [ prev_ ] <EOL> except IndexError : <EOL> raise ChangesetDoesNotExistError <EOL> cs = changeset . repository . get_changeset ( prev_rev ) <EOL> if branch and branch != cs . branch : <EOL> return _prev ( cs , branch ) <EOL> return cs <EOL> return _prev ( self , branch ) <EOL> def diff ( self , ignore_whitespace = True , context = <NUM_LIT:3> ) : <EOL> rev1 = self . parents [ <NUM_LIT:0> ] if self . parents else self . repository . EMPTY_CHANGESET <EOL> rev2 = self <EOL> return '<STR_LIT>' . join ( self . repository . get_diff ( rev1 , rev2 , <EOL> ignore_whitespace = ignore_whitespace , <EOL> context = context ) ) <EOL> def get_file_mode ( self , path ) : <EOL> """<STR_LIT>""" <EOL> self . _get_id_for_path ( path ) <EOL> return self . _stat_modes [ path ] <EOL> def get_file_content ( self , path ) : <EOL> """<STR_LIT>""" <EOL> id = self . _get_id_for_path ( path ) <EOL> blob = self . repository . _repo [ id ] <EOL> return blob . as_pretty_string ( ) <EOL> def get_file_size ( self , path ) : <EOL> """<STR_LIT>""" <EOL> id = self . _get_id_for_path ( path ) <EOL> blob = self . repository . _repo [ id ] <EOL> return blob . raw_length ( ) <EOL> def get_file_changeset ( self , path ) : <EOL> """<STR_LIT>""" <EOL> return self . get_file_history ( path , limit = <NUM_LIT:1> ) [ <NUM_LIT:0> ] <EOL> def get_file_history ( self , path , limit = None ) : <EOL> """<STR_LIT>""" <EOL> self . _get_filectx ( path ) <EOL> cs_id = safe_str ( self . id ) <EOL> f_path = safe_str ( path ) <EOL> if limit : <EOL> cmd = '<STR_LIT>' % ( <EOL> safe_int ( limit , <NUM_LIT:0> ) , cs_id , f_path <EOL> ) <EOL> else : <EOL> cmd = '<STR_LIT>' % ( <EOL> cs_id , f_path <EOL> ) <EOL> so , se = self . repository . run_git_command ( cmd ) <EOL> ids = re . findall ( r'<STR_LIT>' , so ) <EOL> return [ self . repository . get_changeset ( id ) for id in ids ] <EOL> def get_file_history_2 ( self , path ) : <EOL> """<STR_LIT>""" <EOL> self . _get_filectx ( path ) <EOL> from dulwich . walk import Walker <EOL> include = [ self . id ] <EOL> walker = Walker ( self . repository . _repo . object_store , include , <EOL> paths = [ path ] , max_entries = <NUM_LIT:1> ) <EOL> return [ self . repository . get_changeset ( sha ) <EOL> for sha in ( x . commit . id for x in walker ) ] <EOL> def get_file_annotate ( self , path ) : <EOL> """<STR_LIT>""" <EOL> cmd = '<STR_LIT>' % ( self . id , path ) <EOL> so , se = self . repository . run_git_command ( cmd ) <EOL> for i , blame_line in enumerate ( so . split ( '<STR_LIT:\n>' ) [ : - <NUM_LIT:1> ] ) : <EOL> ln_no = i + <NUM_LIT:1> <EOL> sha , line = re . split ( r'<STR_LIT:U+0020>' , blame_line , <NUM_LIT:1> ) <EOL> yield ( ln_no , sha , lambda : self . repository . get_changeset ( sha ) , line ) <EOL> def fill_archive ( self , stream = None , kind = '<STR_LIT>' , prefix = None , <EOL> subrepos = False ) : <EOL> """<STR_LIT>""" <EOL> allowed_kinds = settings . ARCHIVE_SPECS . keys ( ) <EOL> if kind not in allowed_kinds : <EOL> raise ImproperArchiveTypeError ( '<STR_LIT>' <EOL> '<STR_LIT>' , allowed_kinds ) <EOL> if prefix is None : <EOL> prefix = '<STR_LIT>' % ( self . repository . name , self . short_id ) <EOL> elif prefix . startswith ( '<STR_LIT:/>' ) : <EOL> raise VCSError ( "<STR_LIT>" ) <EOL> elif prefix . strip ( ) == '<STR_LIT>' : <EOL> raise VCSError ( "<STR_LIT>" ) <EOL> if kind == '<STR_LIT>' : <EOL> frmt = '<STR_LIT>' <EOL> else : <EOL> frmt = '<STR_LIT>' <EOL> _git_path = settings . GIT_EXECUTABLE_PATH <EOL> cmd = '<STR_LIT>' % ( _git_path , <EOL> frmt , prefix , self . raw_id ) <EOL> if kind == '<STR_LIT>' : <EOL> cmd += '<STR_LIT>' <EOL> elif kind == '<STR_LIT>' : <EOL> cmd += '<STR_LIT>' <EOL> if stream is None : <EOL> raise VCSError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> popen = Popen ( cmd , stdout = PIPE , stderr = PIPE , shell = True , <EOL> cwd = self . repository . path ) <EOL> buffer_size = <NUM_LIT> * <NUM_LIT:8> <EOL> chunk = popen . stdout . read ( buffer_size ) <EOL> while chunk : <EOL> stream . write ( chunk ) <EOL> chunk = popen . stdout . read ( buffer_size ) <EOL> popen . communicate ( ) <EOL> def get_nodes ( self , path ) : <EOL> if self . _get_kind ( path ) != NodeKind . DIR : <EOL> raise ChangesetError ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( self . revision , path ) ) <EOL> path = self . _fix_path ( path ) <EOL> id = self . _get_id_for_path ( path ) <EOL> tree = self . repository . _repo [ id ] <EOL> dirnodes = [ ] <EOL> filenodes = [ ] <EOL> als = self . repository . alias <EOL> for name , stat , id in tree . iteritems ( ) : <EOL> if objects . S_ISGITLINK ( stat ) : <EOL> dirnodes . append ( SubModuleNode ( name , url = None , changeset = id , <EOL> alias = als ) ) <EOL> continue <EOL> obj = self . repository . _repo . get_object ( id ) <EOL> if path != '<STR_LIT>' : <EOL> obj_path = '<STR_LIT:/>' . join ( ( path , name ) ) <EOL> else : <EOL> obj_path = name <EOL> if obj_path not in self . _stat_modes : <EOL> self . _stat_modes [ obj_path ] = stat <EOL> if isinstance ( obj , objects . Tree ) : <EOL> dirnodes . append ( DirNode ( obj_path , changeset = self ) ) <EOL> elif isinstance ( obj , objects . Blob ) : <EOL> filenodes . append ( FileNode ( obj_path , changeset = self , mode = stat ) ) <EOL> else : <EOL> raise ChangesetError ( "<STR_LIT>" <EOL> "<STR_LIT>" % type ( obj ) ) <EOL> nodes = dirnodes + filenodes <EOL> for node in nodes : <EOL> if not node . path in self . nodes : <EOL> self . nodes [ node . path ] = node <EOL> nodes . sort ( ) <EOL> return nodes <EOL> def get_node ( self , path ) : <EOL> if isinstance ( path , unicode ) : <EOL> path = path . encode ( '<STR_LIT:utf-8>' ) <EOL> path = self . _fix_path ( path ) <EOL> if not path in self . nodes : <EOL> try : <EOL> id_ = self . _get_id_for_path ( path ) <EOL> except ChangesetError : <EOL> raise NodeDoesNotExistError ( "<STR_LIT>" <EOL> "<STR_LIT>" % path ) <EOL> _GL = lambda m : m and objects . S_ISGITLINK ( m ) <EOL> if _GL ( self . _stat_modes . get ( path ) ) : <EOL> node = SubModuleNode ( path , url = None , changeset = id_ , <EOL> alias = self . repository . alias ) <EOL> else : <EOL> obj = self . repository . _repo . get_object ( id_ ) <EOL> if isinstance ( obj , objects . Tree ) : <EOL> if path == '<STR_LIT>' : <EOL> node = RootNode ( changeset = self ) <EOL> else : <EOL> node = DirNode ( path , changeset = self ) <EOL> node . _tree = obj <EOL> elif isinstance ( obj , objects . Blob ) : <EOL> node = FileNode ( path , changeset = self ) <EOL> node . _blob = obj <EOL> else : <EOL> raise NodeDoesNotExistError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> % ( path , self . short_id ) ) <EOL> self . nodes [ path ] = node <EOL> return self . nodes [ path ] <EOL> @ LazyProperty <EOL> def affected_files ( self ) : <EOL> """<STR_LIT>""" <EOL> added , modified , deleted = self . _changes_cache <EOL> return list ( added . union ( modified ) . union ( deleted ) ) <EOL> @ LazyProperty <EOL> def _diff_name_status ( self ) : <EOL> output = [ ] <EOL> for parent in self . parents : <EOL> cmd = '<STR_LIT>' % ( parent . raw_id , <EOL> self . raw_id ) <EOL> so , se = self . repository . run_git_command ( cmd ) <EOL> output . append ( so . strip ( ) ) <EOL> return '<STR_LIT:\n>' . join ( output ) <EOL> @ LazyProperty <EOL> def _changes_cache ( self ) : <EOL> added = set ( ) <EOL> modified = set ( ) <EOL> deleted = set ( ) <EOL> _r = self . repository . _repo <EOL> parents = self . parents <EOL> if not self . parents : <EOL> parents = [ EmptyChangeset ( ) ] <EOL> for parent in parents : <EOL> if isinstance ( parent , EmptyChangeset ) : <EOL> oid = None <EOL> else : <EOL> oid = _r [ parent . raw_id ] . tree <EOL> changes = _r . object_store . tree_changes ( oid , _r [ self . raw_id ] . tree ) <EOL> for ( oldpath , newpath ) , ( _ , _ ) , ( _ , _ ) in changes : <EOL> if newpath and oldpath : <EOL> modified . add ( newpath ) <EOL> elif newpath and not oldpath : <EOL> added . add ( newpath ) <EOL> elif not newpath and oldpath : <EOL> deleted . add ( oldpath ) <EOL> return added , modified , deleted <EOL> def _get_paths_for_status ( self , status ) : <EOL> """<STR_LIT>""" <EOL> added , modified , deleted = self . _changes_cache <EOL> return sorted ( { <EOL> '<STR_LIT>' : list ( added ) , <EOL> '<STR_LIT>' : list ( modified ) , <EOL> '<STR_LIT>' : list ( deleted ) } [ status ] <EOL> ) <EOL> @ LazyProperty <EOL> def added ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . parents : <EOL> return list ( self . _get_file_nodes ( ) ) <EOL> return AddedFileNodesGenerator ( [ n for n in <EOL> self . _get_paths_for_status ( '<STR_LIT>' ) ] , self ) <EOL> @ LazyProperty <EOL> def changed ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . parents : <EOL> return [ ] <EOL> return ChangedFileNodesGenerator ( [ n for n in <EOL> self . _get_paths_for_status ( '<STR_LIT>' ) ] , self ) <EOL> @ LazyProperty <EOL> def removed ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . parents : <EOL> return [ ] <EOL> return RemovedFileNodesGenerator ( [ n for n in <EOL> self . _get_paths_for_status ( '<STR_LIT>' ) ] , self ) </s>
