<s> from io import BytesIO <EOL> import re <EOL> import time <EOL> from dulwich . repo import Repo <EOL> from dulwich . objects import Commit , Tree , Blob <EOL> from . import KeyValueStore , __version__ <EOL> def _on_tree ( repo , tree , components , obj ) : <EOL> """<STR_LIT>""" <EOL> if len ( components ) == <NUM_LIT:1> : <EOL> if isinstance ( obj , Blob ) : <EOL> mode = <NUM_LIT> <EOL> elif isinstance ( obj , Tree ) : <EOL> mode = <NUM_LIT> <EOL> elif obj is None : <EOL> mode = None <EOL> else : <EOL> raise TypeError ( '<STR_LIT>' ) <EOL> name = components [ <NUM_LIT:0> ] <EOL> if mode is not None : <EOL> tree [ name ] = mode , obj . id <EOL> return [ tree ] <EOL> if name in tree : <EOL> del tree [ name ] <EOL> return [ tree ] <EOL> elif len ( components ) > <NUM_LIT:1> : <EOL> a , bc = components [ <NUM_LIT:0> ] , components [ <NUM_LIT:1> : ] <EOL> if a in tree : <EOL> a_tree = repo [ tree [ a ] [ <NUM_LIT:1> ] ] <EOL> if not isinstance ( a_tree , Tree ) : <EOL> a_tree = Tree ( ) <EOL> else : <EOL> a_tree = Tree ( ) <EOL> res = _on_tree ( repo , a_tree , bc , obj ) <EOL> a_tree_new = res [ - <NUM_LIT:1> ] <EOL> if a_tree_new . items ( ) : <EOL> tree [ a ] = <NUM_LIT> , a_tree_new . id <EOL> return res + [ tree ] <EOL> if a in tree : <EOL> del tree [ a ] <EOL> return [ tree ] <EOL> else : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> class GitCommitStore ( KeyValueStore ) : <EOL> AUTHOR = '<STR_LIT>' . format ( __version__ ) <EOL> TIMEZONE = None <EOL> def __init__ ( self , repo_path , branch = b'<STR_LIT>' , subdir = b'<STR_LIT>' ) : <EOL> self . repo = Repo ( repo_path ) <EOL> self . branch = branch <EOL> self . subdir = re . sub ( '<STR_LIT>' , '<STR_LIT:/>' , subdir . decode ( '<STR_LIT:ascii>' ) . strip ( '<STR_LIT:/>' ) ) <EOL> @ property <EOL> def _subdir_components ( self ) : <EOL> return [ c . encode ( '<STR_LIT:ascii>' ) for c in self . subdir . split ( '<STR_LIT:/>' ) ] <EOL> @ property <EOL> def _refname ( self ) : <EOL> return b'<STR_LIT>' + self . branch <EOL> def _create_top_commit ( self ) : <EOL> commit = Commit ( ) <EOL> author = self . AUTHOR . encode ( '<STR_LIT:utf8>' ) <EOL> commit . author = commit . committer = author <EOL> commit . commit_time = commit . author_time = int ( time . time ( ) ) <EOL> if self . TIMEZONE is not None : <EOL> tz = self . TIMEZONE <EOL> else : <EOL> tz = time . timezone if ( time . localtime ( ) . tm_isdst ) else time . altzone <EOL> commit . commit_timezone = commit . author_timezone = tz <EOL> commit . encoding = b'<STR_LIT>' <EOL> return commit <EOL> def _delete ( self , key ) : <EOL> try : <EOL> commit = self . repo [ self . _refname ] <EOL> tree = self . repo [ commit . tree ] <EOL> except KeyError : <EOL> return <EOL> commit = self . _create_top_commit ( ) <EOL> objects_to_add = [ ] <EOL> components = [ key . encode ( '<STR_LIT:ascii>' ) ] <EOL> if self . subdir : <EOL> components = self . _subdir_components + components <EOL> res = _on_tree ( self . repo , tree , components , None ) <EOL> objects_to_add . extend ( res ) <EOL> tree = res [ - <NUM_LIT:1> ] <EOL> commit . tree = tree . id <EOL> commit . message = ( <EOL> '<STR_LIT>' . format ( self . subdir + '<STR_LIT:/>' + key ) ) . encode ( '<STR_LIT:utf8>' ) <EOL> objects_to_add . append ( commit ) <EOL> for obj in objects_to_add : <EOL> self . repo . object_store . add_object ( obj ) <EOL> self . repo . refs [ self . _refname ] = commit . id <EOL> def _get ( self , key ) : <EOL> try : <EOL> commit = self . repo [ self . _refname ] <EOL> tree = self . repo [ commit . tree ] <EOL> fn = self . subdir + '<STR_LIT:/>' + key <EOL> _ , blob_id = tree . lookup_path ( self . repo . __getitem__ , <EOL> fn . encode ( '<STR_LIT:ascii>' ) ) <EOL> blob = self . repo [ blob_id ] <EOL> except KeyError : <EOL> raise KeyError ( key ) <EOL> return blob . data <EOL> def iter_keys ( self ) : <EOL> try : <EOL> commit = self . repo [ self . _refname ] <EOL> tree = self . repo [ commit . tree ] <EOL> if self . subdir : <EOL> tree = self . repo [ tree . lookup_path ( <EOL> self . repo . __getitem__ , self . subdir . encode ( '<STR_LIT:ascii>' ) ) [ <NUM_LIT:1> ] ] <EOL> except KeyError : <EOL> pass <EOL> else : <EOL> for name in tree : <EOL> yield name . decode ( '<STR_LIT:ascii>' ) <EOL> def _open ( self , key ) : <EOL> return BytesIO ( self . _get ( key ) ) <EOL> def _put_file ( self , key , file ) : <EOL> return self . _put ( key , file . read ( ) ) <EOL> def _put ( self , key , data ) : <EOL> commit = self . _create_top_commit ( ) <EOL> commit . message = ( <EOL> '<STR_LIT>' . format ( self . subdir + '<STR_LIT:/>' + key ) ) . encode ( '<STR_LIT:utf8>' ) <EOL> blob = Blob . from_string ( data ) <EOL> try : <EOL> parent_commit = self . repo [ self . _refname ] <EOL> except KeyError : <EOL> tree = Tree ( ) <EOL> else : <EOL> commit . parents = [ parent_commit . id ] <EOL> tree = self . repo [ parent_commit . tree ] <EOL> objects_to_add = [ blob ] <EOL> components = [ key . encode ( '<STR_LIT:ascii>' ) ] <EOL> if self . subdir : <EOL> components = self . _subdir_components + components <EOL> res = _on_tree ( self . repo , tree , components , blob ) <EOL> objects_to_add . extend ( res ) <EOL> commit . tree = res [ - <NUM_LIT:1> ] . id <EOL> objects_to_add . append ( commit ) <EOL> for obj in objects_to_add : <EOL> self . repo . object_store . add_object ( obj ) <EOL> self . repo . refs [ self . _refname ] = commit . id <EOL> return key </s>
