<s> from __future__ import unicode_literals <EOL> import bz2 <EOL> import logging <EOL> from django . db import models <EOL> from django . db . models import Q <EOL> from django . utils import six , timezone <EOL> from django . utils . encoding import python_2_unicode_compatible <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from djblets . db . fields import Base64Field , JSONField <EOL> from reviewboard . diffviewer . errors import DiffParserError <EOL> from reviewboard . diffviewer . managers import ( RawFileDiffDataManager , <EOL> FileDiffManager , <EOL> DiffSetManager ) <EOL> from reviewboard . scmtools . core import PRE_CREATION <EOL> from reviewboard . scmtools . models import Repository <EOL> class LegacyFileDiffData ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> binary_hash = models . CharField ( _ ( "<STR_LIT>" ) , max_length = <NUM_LIT> , primary_key = True ) <EOL> binary = Base64Field ( _ ( "<STR_LIT>" ) ) <EOL> extra_data = JSONField ( null = True ) <EOL> class Meta : <EOL> db_table = '<STR_LIT>' <EOL> class RawFileDiffData ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> COMPRESSION_BZIP2 = '<STR_LIT:B>' <EOL> COMPRESSION_CHOICES = ( <EOL> ( COMPRESSION_BZIP2 , _ ( '<STR_LIT>' ) ) , <EOL> ) <EOL> binary_hash = models . CharField ( _ ( "<STR_LIT>" ) , max_length = <NUM_LIT> , unique = True ) <EOL> binary = models . BinaryField ( ) <EOL> compression = models . CharField ( max_length = <NUM_LIT:1> , choices = COMPRESSION_CHOICES , <EOL> null = True , blank = True ) <EOL> extra_data = JSONField ( null = True ) <EOL> objects = RawFileDiffDataManager ( ) <EOL> @ property <EOL> def content ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . compression == self . COMPRESSION_BZIP2 : <EOL> return bz2 . decompress ( self . binary ) <EOL> elif self . compression is None : <EOL> return bytes ( self . binary ) <EOL> else : <EOL> raise NotImplementedError ( <EOL> '<STR_LIT>' <EOL> % ( self . compression , self . pk ) ) <EOL> @ property <EOL> def insert_count ( self ) : <EOL> return self . extra_data . get ( '<STR_LIT>' ) <EOL> @ insert_count . setter <EOL> def insert_count ( self , value ) : <EOL> self . extra_data [ '<STR_LIT>' ] = value <EOL> @ property <EOL> def delete_count ( self ) : <EOL> return self . extra_data . get ( '<STR_LIT>' ) <EOL> @ delete_count . setter <EOL> def delete_count ( self , value ) : <EOL> self . extra_data [ '<STR_LIT>' ] = value <EOL> def recalculate_line_counts ( self , tool ) : <EOL> """<STR_LIT>""" <EOL> logging . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' % self . pk ) <EOL> try : <EOL> files = tool . get_parser ( self . content ) . parse ( ) <EOL> if len ( files ) != <NUM_LIT:1> : <EOL> raise DiffParserError ( <EOL> '<STR_LIT>' % len ( files ) ) <EOL> except DiffParserError as e : <EOL> logging . error ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> self . pk , e ) <EOL> else : <EOL> file_info = files [ <NUM_LIT:0> ] <EOL> self . insert_count = file_info . insert_count <EOL> self . delete_count = file_info . delete_count <EOL> if self . pk : <EOL> self . save ( update_fields = [ '<STR_LIT>' ] ) <EOL> @ python_2_unicode_compatible <EOL> class FileDiff ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> COPIED = '<STR_LIT:C>' <EOL> DELETED = '<STR_LIT:D>' <EOL> MODIFIED = '<STR_LIT:M>' <EOL> MOVED = '<STR_LIT>' <EOL> STATUSES = ( <EOL> ( COPIED , _ ( '<STR_LIT>' ) ) , <EOL> ( DELETED , _ ( '<STR_LIT>' ) ) , <EOL> ( MODIFIED , _ ( '<STR_LIT>' ) ) , <EOL> ( MOVED , _ ( '<STR_LIT>' ) ) , <EOL> ) <EOL> diffset = models . ForeignKey ( '<STR_LIT>' , <EOL> related_name = '<STR_LIT>' , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> source_file = models . CharField ( _ ( "<STR_LIT>" ) , max_length = <NUM_LIT> ) <EOL> dest_file = models . CharField ( _ ( "<STR_LIT>" ) , max_length = <NUM_LIT> ) <EOL> source_revision = models . CharField ( _ ( "<STR_LIT>" ) , <EOL> max_length = <NUM_LIT> ) <EOL> dest_detail = models . CharField ( _ ( "<STR_LIT>" ) , <EOL> max_length = <NUM_LIT> ) <EOL> binary = models . BooleanField ( _ ( "<STR_LIT>" ) , default = False ) <EOL> status = models . CharField ( _ ( "<STR_LIT:status>" ) , max_length = <NUM_LIT:1> , choices = STATUSES ) <EOL> diff64 = Base64Field ( <EOL> _ ( "<STR_LIT>" ) , <EOL> db_column = "<STR_LIT>" , <EOL> blank = True ) <EOL> legacy_diff_hash = models . ForeignKey ( <EOL> LegacyFileDiffData , <EOL> db_column = '<STR_LIT>' , <EOL> related_name = '<STR_LIT>' , <EOL> null = True , <EOL> blank = True ) <EOL> diff_hash = models . ForeignKey ( <EOL> RawFileDiffData , <EOL> db_column = '<STR_LIT>' , <EOL> related_name = '<STR_LIT>' , <EOL> null = True , <EOL> blank = True ) <EOL> parent_diff64 = Base64Field ( <EOL> _ ( "<STR_LIT>" ) , <EOL> db_column = "<STR_LIT>" , <EOL> blank = True ) <EOL> legacy_parent_diff_hash = models . ForeignKey ( <EOL> LegacyFileDiffData , <EOL> db_column = '<STR_LIT>' , <EOL> related_name = '<STR_LIT>' , <EOL> null = True , <EOL> blank = True ) <EOL> parent_diff_hash = models . ForeignKey ( <EOL> RawFileDiffData , <EOL> db_column = '<STR_LIT>' , <EOL> related_name = '<STR_LIT>' , <EOL> null = True , <EOL> blank = True ) <EOL> extra_data = JSONField ( null = True ) <EOL> objects = FileDiffManager ( ) <EOL> @ property <EOL> def source_file_display ( self ) : <EOL> tool = self . diffset . repository . get_scmtool ( ) <EOL> return tool . normalize_path_for_display ( self . source_file ) <EOL> @ property <EOL> def dest_file_display ( self ) : <EOL> tool = self . diffset . repository . get_scmtool ( ) <EOL> return tool . normalize_path_for_display ( self . dest_file ) <EOL> @ property <EOL> def deleted ( self ) : <EOL> return self . status == self . DELETED <EOL> @ property <EOL> def copied ( self ) : <EOL> return self . status == self . COPIED <EOL> @ property <EOL> def moved ( self ) : <EOL> return self . status == self . MOVED <EOL> @ property <EOL> def is_new ( self ) : <EOL> return self . source_revision == PRE_CREATION <EOL> def _get_diff ( self ) : <EOL> if self . _needs_diff_migration ( ) : <EOL> self . _migrate_diff_data ( ) <EOL> return self . diff_hash . content <EOL> def _set_diff ( self , diff ) : <EOL> self . diff_hash , is_new = RawFileDiffData . objects . get_or_create_from_data ( diff ) <EOL> self . diff64 = "<STR_LIT>" <EOL> return is_new <EOL> diff = property ( _get_diff , _set_diff ) <EOL> def _get_parent_diff ( self ) : <EOL> if self . _needs_parent_diff_migration ( ) : <EOL> self . _migrate_diff_data ( ) <EOL> if self . parent_diff_hash : <EOL> return self . parent_diff_hash . content <EOL> else : <EOL> return None <EOL> def _set_parent_diff ( self , parent_diff ) : <EOL> if not parent_diff : <EOL> return False <EOL> self . parent_diff_hash , is_new = RawFileDiffData . objects . get_or_create_from_data ( parent_diff ) <EOL> self . parent_diff64 = '<STR_LIT>' <EOL> return is_new <EOL> parent_diff = property ( _get_parent_diff , _set_parent_diff ) <EOL> @ property <EOL> def orig_sha1 ( self ) : <EOL> return self . extra_data . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def patched_sha1 ( self ) : <EOL> return self . extra_data . get ( '<STR_LIT>' ) <EOL> def get_line_counts ( self ) : <EOL> """<STR_LIT>""" <EOL> if ( '<STR_LIT>' not in self . extra_data or <EOL> '<STR_LIT>' not in self . extra_data ) : <EOL> if not self . diff_hash : <EOL> self . _migrate_diff_data ( ) <EOL> if self . diff_hash . insert_count is None : <EOL> self . _recalculate_line_counts ( self . diff_hash ) <EOL> self . extra_data . update ( { <EOL> '<STR_LIT>' : self . diff_hash . insert_count , <EOL> '<STR_LIT>' : self . diff_hash . delete_count , <EOL> } ) <EOL> if self . pk : <EOL> self . save ( update_fields = [ '<STR_LIT>' ] ) <EOL> raw_insert_count = self . extra_data [ '<STR_LIT>' ] <EOL> raw_delete_count = self . extra_data [ '<STR_LIT>' ] <EOL> return { <EOL> '<STR_LIT>' : raw_insert_count , <EOL> '<STR_LIT>' : raw_delete_count , <EOL> '<STR_LIT>' : self . extra_data . get ( '<STR_LIT>' , <EOL> raw_insert_count ) , <EOL> '<STR_LIT>' : self . extra_data . get ( '<STR_LIT>' , <EOL> raw_delete_count ) , <EOL> '<STR_LIT>' : self . extra_data . get ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : self . extra_data . get ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : self . extra_data . get ( '<STR_LIT>' ) , <EOL> } <EOL> def set_line_counts ( self , raw_insert_count = None , raw_delete_count = None , <EOL> insert_count = None , delete_count = None , <EOL> replace_count = None , equal_count = None , <EOL> total_line_count = None ) : <EOL> """<STR_LIT>""" <EOL> updated = False <EOL> if not self . diff_hash_id : <EOL> logging . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' % self . pk ) <EOL> self . _migrate_diff_data ( False ) <EOL> if ( insert_count is not None and <EOL> raw_insert_count is not None and <EOL> self . diff_hash . insert_count is not None and <EOL> self . diff_hash . insert_count != insert_count ) : <EOL> logging . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> % ( self . diff_hash . pk , <EOL> self . diff_hash . insert_count , <EOL> insert_count , <EOL> self . pk ) ) <EOL> if ( delete_count is not None and <EOL> raw_delete_count is not None and <EOL> self . diff_hash . delete_count is not None and <EOL> self . diff_hash . delete_count != delete_count ) : <EOL> logging . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> % ( self . diff_hash . pk , <EOL> self . diff_hash . delete_count , <EOL> delete_count , <EOL> self . pk ) ) <EOL> if raw_insert_count is not None or raw_delete_count is not None : <EOL> if raw_insert_count is not None : <EOL> self . diff_hash . insert_count = raw_insert_count <EOL> self . extra_data [ '<STR_LIT>' ] = raw_insert_count <EOL> updated = True <EOL> if raw_delete_count is not None : <EOL> self . diff_hash . delete_count = raw_delete_count <EOL> self . extra_data [ '<STR_LIT>' ] = raw_delete_count <EOL> updated = True <EOL> self . diff_hash . save ( ) <EOL> for key , cur_value in ( ( '<STR_LIT>' , insert_count ) , <EOL> ( '<STR_LIT>' , delete_count ) , <EOL> ( '<STR_LIT>' , replace_count ) , <EOL> ( '<STR_LIT>' , equal_count ) , <EOL> ( '<STR_LIT>' , total_line_count ) ) : <EOL> if cur_value is not None and cur_value != self . extra_data . get ( key ) : <EOL> self . extra_data [ key ] = cur_value <EOL> updated = True <EOL> if updated and self . pk : <EOL> self . save ( update_fields = [ '<STR_LIT>' ] ) <EOL> def _needs_diff_migration ( self ) : <EOL> return self . diff_hash_id is None <EOL> def _needs_parent_diff_migration ( self ) : <EOL> return ( self . parent_diff_hash_id is None and <EOL> ( self . parent_diff64 or self . legacy_parent_diff_hash_id ) ) <EOL> def _migrate_diff_data ( self , recalculate_counts = True ) : <EOL> """<STR_LIT>""" <EOL> needs_save = False <EOL> diff_hash_is_new = False <EOL> parent_diff_hash_is_new = False <EOL> legacy_pks = [ ] <EOL> if self . _needs_diff_migration ( ) : <EOL> needs_save = True <EOL> if self . legacy_diff_hash_id : <EOL> logging . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> self . legacy_diff_hash_id , self . pk ) <EOL> diff_hash_is_new = self . _set_diff ( self . legacy_diff_hash . binary ) <EOL> legacy_pks . append ( self . legacy_diff_hash_id ) <EOL> self . legacy_diff_hash = None <EOL> else : <EOL> logging . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> self . pk ) <EOL> diff_hash_is_new = self . _set_diff ( self . diff64 ) <EOL> if recalculate_counts : <EOL> self . _recalculate_line_counts ( self . diff_hash ) <EOL> if self . _needs_parent_diff_migration ( ) : <EOL> needs_save = True <EOL> if self . legacy_parent_diff_hash_id : <EOL> logging . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> self . legacy_parent_diff_hash_id , self . pk ) <EOL> parent_diff_hash_is_new = self . _set_parent_diff ( self . legacy_parent_diff_hash . binary ) <EOL> legacy_pks . append ( self . legacy_parent_diff_hash_id ) <EOL> self . legacy_parent_diff_hash = None <EOL> else : <EOL> logging . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> self . pk ) <EOL> parent_diff_hash_is_new = self . _set_parent_diff ( self . parent_diff64 ) <EOL> if recalculate_counts : <EOL> self . _recalculate_line_counts ( self . parent_diff_hash ) <EOL> if needs_save : <EOL> self . save ( ) <EOL> if legacy_pks : <EOL> LegacyFileDiffData . objects . filter ( pk__in = legacy_pks ) . exclude ( Q ( filediffs__pk__gt = <NUM_LIT:0> ) | <EOL> Q ( parent_filediffs__pk__gt = <NUM_LIT:0> ) ) . delete ( ) <EOL> return diff_hash_is_new , parent_diff_hash_is_new <EOL> def _recalculate_line_counts ( self , diff_hash ) : <EOL> """<STR_LIT>""" <EOL> diff_hash . recalculate_line_counts ( <EOL> self . diffset . repository . get_scmtool ( ) ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . source_file , self . source_revision , <EOL> self . dest_file , self . dest_detail ) <EOL> @ python_2_unicode_compatible <EOL> class DiffSet ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> name = models . CharField ( _ ( '<STR_LIT:name>' ) , max_length = <NUM_LIT> ) <EOL> revision = models . IntegerField ( _ ( "<STR_LIT>" ) ) <EOL> timestamp = models . DateTimeField ( _ ( "<STR_LIT>" ) , default = timezone . now ) <EOL> basedir = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT> , <EOL> blank = True , default = '<STR_LIT>' ) <EOL> history = models . ForeignKey ( '<STR_LIT>' , null = True , <EOL> related_name = "<STR_LIT>" , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> repository = models . ForeignKey ( Repository , related_name = "<STR_LIT>" , <EOL> verbose_name = _ ( "<STR_LIT>" ) ) <EOL> diffcompat = models . IntegerField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> default = <NUM_LIT:0> , <EOL> help_text = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> base_commit_id = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:64> , blank = True , null = True , db_index = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> extra_data = JSONField ( null = True ) <EOL> objects = DiffSetManager ( ) <EOL> def get_total_line_counts ( self ) : <EOL> """<STR_LIT>""" <EOL> counts = { } <EOL> for filediff in self . files . all ( ) : <EOL> for key , value in six . iteritems ( filediff . get_line_counts ( ) ) : <EOL> if counts . get ( key ) is None : <EOL> counts [ key ] = value <EOL> elif value is not None : <EOL> counts [ key ] += value <EOL> return counts <EOL> def save ( self , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if self . revision == <NUM_LIT:0> and self . history is not None : <EOL> if self . history . diffsets . count ( ) == <NUM_LIT:0> : <EOL> self . revision = <NUM_LIT:1> <EOL> else : <EOL> self . revision = self . history . diffsets . latest ( ) . revision + <NUM_LIT:1> <EOL> if self . history : <EOL> self . history . last_diff_updated = self . timestamp <EOL> self . history . save ( ) <EOL> super ( DiffSet , self ) . save ( ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . id , self . name , self . revision ) <EOL> class Meta : <EOL> get_latest_by = '<STR_LIT>' <EOL> ordering = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> @ python_2_unicode_compatible <EOL> class DiffSetHistory ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> name = models . CharField ( _ ( '<STR_LIT:name>' ) , max_length = <NUM_LIT> ) <EOL> timestamp = models . DateTimeField ( _ ( "<STR_LIT>" ) , default = timezone . now ) <EOL> last_diff_updated = models . DateTimeField ( <EOL> _ ( "<STR_LIT>" ) , <EOL> blank = True , <EOL> null = True , <EOL> default = None ) <EOL> extra_data = JSONField ( null = True ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % self . diffsets . count ( ) <EOL> class Meta : <EOL> verbose_name_plural = "<STR_LIT>" </s>
