<s> from __future__ import unicode_literals <EOL> import logging <EOL> import os <EOL> import random <EOL> import re <EOL> import shutil <EOL> import signal <EOL> import socket <EOL> import subprocess <EOL> import tempfile <EOL> import time <EOL> from contextlib import contextmanager <EOL> from django . utils import six <EOL> from django . utils . functional import cached_property <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from djblets . util . filesystem import is_exe_in_path <EOL> from reviewboard . diffviewer . parser import DiffParser <EOL> from reviewboard . scmtools . certs import Certificate <EOL> from reviewboard . scmtools . core import ( SCMTool , ChangeSet , <EOL> HEAD , PRE_CREATION ) <EOL> from reviewboard . scmtools . errors import ( SCMError , EmptyChangeSetError , <EOL> AuthenticationError , <EOL> RepositoryNotFoundError , <EOL> UnverifiedCertificateError ) <EOL> STUNNEL_SERVER , STUNNEL_CLIENT = ( <NUM_LIT:0> , <NUM_LIT:1> ) <EOL> class STunnelProxy ( object ) : <EOL> def __init__ ( self , mode , target ) : <EOL> if not is_exe_in_path ( '<STR_LIT>' ) : <EOL> raise OSError ( '<STR_LIT>' ) <EOL> if mode not in ( STUNNEL_SERVER , STUNNEL_CLIENT ) : <EOL> raise AttributeError <EOL> self . mode = mode <EOL> self . target = target <EOL> self . pid = None <EOL> @ cached_property <EOL> def stunnel_use_config ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> subprocess . check_call ( [ '<STR_LIT>' , '<STR_LIT>' ] , <EOL> stdout = subprocess . PIPE , <EOL> stderr = subprocess . PIPE ) <EOL> return True <EOL> except subprocess . CalledProcessError : <EOL> return False <EOL> def start_server ( self , certfile ) : <EOL> self . _start ( server = True , certfile = certfile ) <EOL> def start_client ( self ) : <EOL> self . _start ( server = False ) <EOL> def _start ( self , server , certfile = None ) : <EOL> self . port = self . _find_port ( ) <EOL> tempdir = tempfile . mkdtemp ( ) <EOL> pid_filename = os . path . join ( tempdir , '<STR_LIT>' ) <EOL> if self . stunnel_use_config : <EOL> conf_filename = os . path . join ( tempdir , '<STR_LIT>' ) <EOL> with open ( conf_filename , '<STR_LIT:w>' ) as fp : <EOL> fp . write ( '<STR_LIT>' % pid_filename ) <EOL> if server : <EOL> fp . write ( '<STR_LIT>' ) <EOL> if certfile : <EOL> fp . write ( '<STR_LIT>' % certfile ) <EOL> fp . write ( '<STR_LIT>' % self . port ) <EOL> fp . write ( '<STR_LIT>' % self . target ) <EOL> else : <EOL> fp . write ( '<STR_LIT>' ) <EOL> fp . write ( '<STR_LIT>' ) <EOL> fp . write ( '<STR_LIT>' % self . port ) <EOL> fp . write ( '<STR_LIT>' % self . target ) <EOL> args = [ conf_filename ] <EOL> else : <EOL> args = [ <EOL> '<STR_LIT>' , pid_filename , <EOL> '<STR_LIT>' , '<STR_LIT>' % self . port , <EOL> '<STR_LIT>' , self . target , <EOL> ] <EOL> if server : <EOL> args += [ '<STR_LIT>' , certfile ] <EOL> else : <EOL> args . append ( '<STR_LIT:-c>' ) <EOL> try : <EOL> subprocess . check_call ( [ '<STR_LIT>' ] + args ) <EOL> except subprocess . CalledProcessError : <EOL> if self . stunnel_use_config : <EOL> with open ( conf_filename , '<STR_LIT:r>' ) as fp : <EOL> logging . error ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> % fp . read ( ) ) <EOL> else : <EOL> logging . error ( '<STR_LIT>' <EOL> % '<STR_LIT:U+0020>' . join ( args ) ) <EOL> else : <EOL> time . sleep ( <NUM_LIT:0.1> ) <EOL> try : <EOL> with open ( pid_filename ) as f : <EOL> self . pid = int ( f . read ( ) ) <EOL> f . close ( ) <EOL> except IOError as e : <EOL> logging . exception ( '<STR_LIT>' <EOL> % ( pid_filename , e ) ) <EOL> shutil . rmtree ( tempdir ) <EOL> def shutdown ( self ) : <EOL> if self . pid : <EOL> os . kill ( self . pid , signal . SIGTERM ) <EOL> self . pid = None <EOL> def _find_port ( self ) : <EOL> """<STR_LIT>""" <EOL> while True : <EOL> port = random . randint ( <NUM_LIT> , <NUM_LIT> ) <EOL> s = socket . socket ( socket . AF_INET , socket . SOCK_STREAM ) <EOL> try : <EOL> s . bind ( ( '<STR_LIT:127.0.0.1>' , port ) ) <EOL> s . listen ( <NUM_LIT:1> ) <EOL> return port <EOL> finally : <EOL> try : <EOL> s . close ( ) <EOL> except : <EOL> pass <EOL> class PerforceClient ( object ) : <EOL> def __init__ ( self , p4port , username , password , encoding , p4host = None , <EOL> use_stunnel = False , use_ticket_auth = False ) : <EOL> self . p4port = p4port <EOL> self . username = username <EOL> self . password = password <EOL> self . encoding = encoding <EOL> self . p4host = p4host <EOL> self . use_stunnel = use_stunnel <EOL> self . use_ticket_auth = use_ticket_auth <EOL> self . proxy = None <EOL> import P4 <EOL> self . p4 = P4 . P4 ( ) <EOL> if use_stunnel and not is_exe_in_path ( '<STR_LIT>' ) : <EOL> raise AttributeError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> @ contextmanager <EOL> def _connect ( self ) : <EOL> """<STR_LIT>""" <EOL> self . p4 . user = self . username . encode ( '<STR_LIT:utf-8>' ) <EOL> self . p4 . password = self . password . encode ( '<STR_LIT:utf-8>' ) <EOL> if self . encoding : <EOL> self . p4 . charset = self . encoding . encode ( '<STR_LIT:utf-8>' ) <EOL> self . p4 . exception_level = <NUM_LIT:1> <EOL> if self . use_stunnel : <EOL> self . proxy = STunnelProxy ( STUNNEL_CLIENT , self . p4port ) <EOL> self . proxy . start_client ( ) <EOL> p4_port = '<STR_LIT>' % self . proxy . port <EOL> else : <EOL> p4_port = self . p4port <EOL> self . p4 . port = p4_port . encode ( '<STR_LIT:utf-8>' ) <EOL> if self . p4host : <EOL> self . p4 . host = self . p4host . encode ( '<STR_LIT:utf-8>' ) <EOL> self . p4 . connect ( ) <EOL> if self . use_ticket_auth : <EOL> self . p4 . run_login ( ) <EOL> yield <EOL> self . _disconnect ( ) <EOL> def _disconnect ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> if self . p4 . connected ( ) : <EOL> self . p4 . disconnect ( ) <EOL> except AttributeError : <EOL> pass <EOL> if self . proxy : <EOL> try : <EOL> self . proxy . shutdown ( ) <EOL> except : <EOL> pass <EOL> self . proxy = None <EOL> @ staticmethod <EOL> def _convert_p4exception_to_scmexception ( e ) : <EOL> error = six . text_type ( e ) <EOL> if '<STR_LIT>' in error or '<STR_LIT>' in error : <EOL> raise AuthenticationError ( msg = error ) <EOL> elif '<STR_LIT>' in error : <EOL> raise SCMError ( _ ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) ) <EOL> elif ( '<STR_LIT>' in error or <EOL> ( error . startswith ( '<STR_LIT>' ) and <EOL> '<STR_LIT>' in error ) ) : <EOL> raise RepositoryNotFoundError <EOL> elif "<STR_LIT>" in error : <EOL> fingerprint = error . split ( '<STR_LIT>' ) [ <NUM_LIT:3> ] <EOL> raise UnverifiedCertificateError ( <EOL> Certificate ( fingerprint = fingerprint ) ) <EOL> else : <EOL> raise SCMError ( error ) <EOL> def _run_worker ( self , worker ) : <EOL> from P4 import P4Exception <EOL> try : <EOL> with self . _connect ( ) : <EOL> return worker ( ) <EOL> except P4Exception as e : <EOL> self . _convert_p4exception_to_scmexception ( e ) <EOL> def _get_changeset ( self , changesetid ) : <EOL> changesetid = six . text_type ( changesetid ) <EOL> try : <EOL> change = self . p4 . run_change ( '<STR_LIT>' , '<STR_LIT>' , changesetid ) <EOL> changesetid = change [ <NUM_LIT:0> ] [ '<STR_LIT>' ] <EOL> except Exception as e : <EOL> logging . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> changesetid , self . p4port , e , exc_info = True ) <EOL> return self . p4 . run_describe ( '<STR_LIT>' , changesetid ) <EOL> def get_changeset ( self , changesetid ) : <EOL> """<STR_LIT>""" <EOL> return self . _run_worker ( lambda : self . _get_changeset ( changesetid ) ) <EOL> def get_info ( self ) : <EOL> return self . _run_worker ( self . p4 . run_info ) <EOL> def _get_file ( self , path , revision ) : <EOL> if revision == PRE_CREATION : <EOL> return '<STR_LIT>' <EOL> elif revision == HEAD : <EOL> depot_path = path <EOL> else : <EOL> depot_path = '<STR_LIT>' % ( path , revision ) <EOL> res = self . p4 . run_print ( '<STR_LIT>' , depot_path ) <EOL> if res : <EOL> return res [ - <NUM_LIT:1> ] <EOL> def get_file ( self , path , revision ) : <EOL> """<STR_LIT>""" <EOL> return self . _run_worker ( lambda : self . _get_file ( path , revision ) ) <EOL> def _get_files_at_revision ( self , revision_str ) : <EOL> return self . p4 . run_files ( revision_str ) <EOL> def get_files_at_revision ( self , revision_str ) : <EOL> """<STR_LIT>""" <EOL> return self . _run_worker ( <EOL> lambda : self . _get_files_at_revision ( revision_str ) ) <EOL> class PerforceTool ( SCMTool ) : <EOL> name = "<STR_LIT>" <EOL> supports_ticket_auth = True <EOL> supports_pending_changesets = True <EOL> field_help_text = { <EOL> '<STR_LIT:path>' : _ ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) , <EOL> } <EOL> dependencies = { <EOL> '<STR_LIT>' : [ '<STR_LIT>' ] , <EOL> } <EOL> def __init__ ( self , repository ) : <EOL> SCMTool . __init__ ( self , repository ) <EOL> credentials = repository . get_credentials ( ) <EOL> self . client = self . _create_client ( <EOL> path = six . text_type ( repository . mirror_path or repository . path ) , <EOL> username = six . text_type ( credentials [ '<STR_LIT:username>' ] ) , <EOL> password = six . text_type ( credentials [ '<STR_LIT:password>' ] or '<STR_LIT>' ) , <EOL> encoding = six . text_type ( repository . encoding ) , <EOL> host = six . text_type ( repository . extra_data . get ( '<STR_LIT>' , '<STR_LIT>' ) ) , <EOL> use_ticket_auth = repository . extra_data . get ( '<STR_LIT>' , <EOL> False ) ) <EOL> @ staticmethod <EOL> def _create_client ( path , username , password , encoding = '<STR_LIT>' , host = None , <EOL> use_ticket_auth = False ) : <EOL> if path . startswith ( '<STR_LIT>' ) : <EOL> path = path [ <NUM_LIT:8> : ] <EOL> use_stunnel = True <EOL> else : <EOL> use_stunnel = False <EOL> return PerforceClient ( path , username , password , encoding , host , <EOL> use_stunnel , use_ticket_auth ) <EOL> @ staticmethod <EOL> def _convert_p4exception_to_scmexception ( e ) : <EOL> error = six . text_type ( e ) <EOL> if '<STR_LIT>' in error or '<STR_LIT>' in error : <EOL> raise AuthenticationError ( msg = error ) <EOL> elif '<STR_LIT>' in error : <EOL> raise RepositoryNotFoundError <EOL> else : <EOL> raise SCMError ( error ) <EOL> @ classmethod <EOL> def check_repository ( cls , path , username = None , password = None , <EOL> p4_host = None , local_site_name = None ) : <EOL> """<STR_LIT>""" <EOL> super ( PerforceTool , cls ) . check_repository ( path , username , password , <EOL> local_site_name ) <EOL> client = cls . _create_client ( six . text_type ( path ) , <EOL> six . text_type ( username ) , <EOL> six . text_type ( password ) , <EOL> host = six . text_type ( p4_host or '<STR_LIT>' ) ) <EOL> client . get_info ( ) <EOL> def get_changeset ( self , changesetid , allow_empty = False ) : <EOL> changeset = self . client . get_changeset ( changesetid ) <EOL> if changeset : <EOL> return self . parse_change_desc ( changeset [ <NUM_LIT:0> ] , changesetid , <EOL> allow_empty ) <EOL> else : <EOL> return None <EOL> def get_diffs_use_absolute_paths ( self ) : <EOL> return True <EOL> def get_file ( self , path , revision = HEAD , ** kwargs ) : <EOL> return self . client . get_file ( path , revision ) <EOL> def parse_diff_revision ( self , file_str , revision_str , * args , ** kwargs ) : <EOL> filename , revision = revision_str . rsplit ( '<STR_LIT:#>' , <NUM_LIT:1> ) <EOL> if len ( self . client . get_files_at_revision ( revision_str ) ) == <NUM_LIT:0> : <EOL> revision = PRE_CREATION <EOL> return filename , revision <EOL> @ staticmethod <EOL> def parse_change_desc ( changedesc , changenum , allow_empty = False ) : <EOL> if not changedesc : <EOL> return None <EOL> changeset = ChangeSet ( ) <EOL> try : <EOL> changeset . changenum = int ( changedesc [ '<STR_LIT>' ] ) <EOL> except ValueError : <EOL> changeset . changenum = changenum <EOL> changeset . username = changedesc [ '<STR_LIT:user>' ] <EOL> try : <EOL> changeset . description = changedesc [ '<STR_LIT>' ] . decode ( '<STR_LIT:utf-8>' ) <EOL> except UnicodeDecodeError : <EOL> changeset . description = changedesc [ '<STR_LIT>' ] . decode ( '<STR_LIT:utf-8>' , <EOL> '<STR_LIT:replace>' ) <EOL> if changedesc [ '<STR_LIT:status>' ] == "<STR_LIT>" : <EOL> changeset . pending = True <EOL> try : <EOL> changeset . files = changedesc [ '<STR_LIT>' ] <EOL> except KeyError : <EOL> if not allow_empty : <EOL> raise EmptyChangeSetError ( changenum ) <EOL> split = changeset . description . find ( '<STR_LIT>' ) <EOL> if split >= <NUM_LIT:0> and split < <NUM_LIT:100> : <EOL> changeset . summary = changeset . description . split ( '<STR_LIT>' , <NUM_LIT:1> ) [ <NUM_LIT:0> ] . replace ( '<STR_LIT:\n>' , '<STR_LIT:U+0020>' ) <EOL> else : <EOL> changeset . summary = changeset . description . split ( '<STR_LIT:\n>' , <NUM_LIT:1> ) [ <NUM_LIT:0> ] <EOL> return changeset <EOL> def get_fields ( self ) : <EOL> return [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> def get_parser ( self , data ) : <EOL> return PerforceDiffParser ( data ) <EOL> @ classmethod <EOL> def accept_certificate ( cls , path , username = None , password = None , <EOL> local_site_name = None , certificate = None ) : <EOL> """<STR_LIT>""" <EOL> args = [ '<STR_LIT>' , '<STR_LIT>' , path , '<STR_LIT>' , '<STR_LIT>' , certificate . fingerprint ] <EOL> p = subprocess . Popen ( args , stdout = subprocess . PIPE , <EOL> stderr = subprocess . PIPE ) <EOL> _ , errdata = p . communicate ( ) <EOL> failure = p . poll ( ) <EOL> if failure : <EOL> raise IOError ( errdata ) <EOL> return certificate . fingerprint <EOL> def normalize_patch ( self , patch , filename , revision ) : <EOL> m = PerforceDiffParser . SPECIAL_REGEX . match ( patch . strip ( ) ) <EOL> if m and m . group ( <NUM_LIT:3> ) == '<STR_LIT>' : <EOL> return '<STR_LIT>' <EOL> return patch <EOL> class PerforceDiffParser ( DiffParser ) : <EOL> SPECIAL_REGEX = re . compile ( "<STR_LIT>" ) <EOL> def __init__ ( self , data ) : <EOL> DiffParser . __init__ ( self , data ) <EOL> def parse_diff_header ( self , linenum , info ) : <EOL> m = self . SPECIAL_REGEX . match ( self . lines [ linenum ] ) <EOL> if m : <EOL> info [ '<STR_LIT>' ] = m . group ( <NUM_LIT:1> ) <EOL> info [ '<STR_LIT>' ] = "<STR_LIT>" % ( m . group ( <NUM_LIT:1> ) , m . group ( <NUM_LIT:2> ) ) <EOL> info [ '<STR_LIT>' ] = m . group ( <NUM_LIT:4> ) <EOL> info [ '<STR_LIT>' ] = "<STR_LIT>" <EOL> linenum += <NUM_LIT:1> <EOL> if linenum < len ( self . lines ) and ( self . lines [ linenum ] . startswith ( b"<STR_LIT>" ) or <EOL> self . lines [ linenum ] . startswith ( b"<STR_LIT>" ) ) : <EOL> info [ '<STR_LIT>' ] = True <EOL> linenum += <NUM_LIT:1> <EOL> change_type = m . group ( <NUM_LIT:3> ) <EOL> if change_type == '<STR_LIT:D>' : <EOL> info [ '<STR_LIT>' ] = True <EOL> elif change_type == '<STR_LIT>' : <EOL> info [ '<STR_LIT>' ] = True <EOL> return linenum <EOL> return super ( PerforceDiffParser , self ) . parse_diff_header ( linenum , info ) <EOL> def parse_special_header ( self , linenum , info ) : <EOL> linenum = super ( PerforceDiffParser , self ) . parse_special_header ( <EOL> linenum , info ) <EOL> if ( linenum + <NUM_LIT:2> < len ( self . lines ) and <EOL> self . lines [ linenum ] . startswith ( b'<STR_LIT>' ) and <EOL> self . lines [ linenum + <NUM_LIT:1> ] . startswith ( b'<STR_LIT>' ) ) : <EOL> info [ '<STR_LIT>' ] = True <EOL> linenum += <NUM_LIT:2> <EOL> return linenum <EOL> def normalize_diff_filename ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> return filename </s>
