def _discover_config_file(self): """Discover the status of the repo config file.""" server_rev = self._get_server_repo_config_rev() config_path = p4gf_config.depot_path_repo(self.repo_name) (head_rev, head_action, head_change) = p4gf_util.depot_file_head_rev_action( self.p4, config_path) was_initialized = server_rev != '0' deleted = head_action and 'delete' in head_action exists = head_action and 'delete' not in head_action readded = was_initialized and exists and p4gf_util.depot_file_is_re_added( self.p4, config_path, server_rev, head_rev) if readded: return (CONFIG_READDED, head_rev, head_change) if exists: if was_initialized: if head_rev == server_rev: self.config_needs_validation = False return (CONFIG_EXISTS, head_rev, head_change) else: return (CONFIG_NEW, head_rev, head_change) if deleted: # The p4gf_config file has been deleted and we will not resurrect from # a p4 client of the same name. return (CONFIG_DELETED, head_rev, head_change) if was_initialized: # The p4gf_config file has apparently been obliterated. return (CONFIG_MISSING, head_rev, head_change) return (CONFIG_NONE, head_rev, head_change)
def from_depot_p4gf_config(view_name, p4): ''' initialize from config file stored in depot''' v = Validator() v.view_name = view_name v.config_file_path = p4gf_config.depot_path_repo(view_name) # Do _not_ use a shared instance, since we explicitly release it later; # instead, get a fresh, unmerged copy for validation purposes. v.config = p4gf_config.read_repo(p4, view_name) v.config_merged = Validator._combine_repo_with_global(p4, v.config) v.p4 = p4 return v
def get_branch_dict(self): """Get a branch dictionary for this repo. If the p4gf_config exists, use that. Else if the p4 client exists create a branch dict containing a branch from the client views. Else return None """ LOG.debug("get_branch_dict for {0}".format(self.view_name)) # Repo config file already checked into Perforce? # Use that. config_path = p4gf_config.depot_path_repo(self.view_name) config_exists = p4gf_util.depot_file_exists(self.p4, config_path) if config_exists: self.config = p4gf_config.get_repo(self.p4, self.view_name) if self.config: return p4gf_branch.dict_from_config(self.config, self.p4) else: return None else: LOG.debug("checking if client {0} exists.".format(self.view_name)) if not p4gf_util.spec_exists(self.p4, 'client', self.view_name): LOG.debug(" client {0} NOT exists.".format( self.view_name)) return None view_lines = p4gf_util.first_value_for_key( self.p4.run('client', '-o', '-t', self.view_name, self.p4client), 'View') if not view_lines: return None else: # create a Branch object to manage this client view if isinstance(view_lines, str): view_lines = view_lines.splitlines() LOG.debug( "create branch from client views: {0}".format(view_lines)) branch = p4gf_branch.Branch() branch.branch_id = 'master' branch.git_branch_name = 'master' branch.view_p4map = P4.Map(view_lines) branch.view_lines = view_lines LOG.debug( "create branch from client branch view_p4map: {0}".format( branch.view_p4map)) LOG.debug( "create branch from client branch view_lines: {0}".format( branch.view_lines)) branch_dict = {} branch_dict[branch.branch_id] = branch return branch_dict
def get_branch_dict(self): """Get a branch dictionary for this repo. If the p4gf_config exists, use that. Else if the p4 client exists create a branch dict containing a branch from the client views. Else return None """ LOG.debug("get_branch_dict for {0}".format(self.view_name)) # Repo config file already checked into Perforce? # Use that. config_path = p4gf_config.depot_path_repo(self.view_name) config_exists = p4gf_util.depot_file_exists(self.p4, config_path) if config_exists: self.config = p4gf_config.get_repo(self.p4, self.view_name) if self.config: return p4gf_branch.dict_from_config(self.config, self.p4) else: return None else: LOG.debug("checking if client {0} exists.".format(self.view_name)) if not p4gf_util.spec_exists(self.p4, 'client', self.view_name): LOG.debug(" client {0} NOT exists.".format(self.view_name)) return None view_lines = p4gf_util.first_value_for_key( self.p4.run('client', '-o', '-t', self.view_name, self.p4client), 'View') if not view_lines: return None else: # create a Branch object to manage this client view if isinstance(view_lines, str): view_lines = view_lines.splitlines() LOG.debug("create branch from client views: {0}".format(view_lines)) branch = p4gf_branch.Branch() branch.branch_id = 'master' branch.git_branch_name = 'master' branch.view_p4map = P4.Map(view_lines) branch.view_lines = view_lines LOG.debug("create branch from client branch view_p4map: {0}". format(branch.view_p4map)) LOG.debug("create branch from client branch view_lines: {0}". format(branch.view_lines)) branch_dict = {} branch_dict[branch.branch_id] = branch return branch_dict
def _create_p4_client(p4, view_name, client_name, client_root, enable_mismatched_rhs, view_name_p4client, handle_imports=True): """Create the p4 client to contain Git meta-data mirror. Keyword arguments: p4 -- Perforce client API view_name -- client view of repository to clone - internal (translated) viewname client_name -- client that will be created client_root -- path for client workspace enable_mismatched_rhs -- allow branches to have differing RHS? view_name_p4client -- name of actual p4 client on which to base this new repo if None - will be determined from view_name if needed Returns one of the INIT_REPO_* constants. """ # Ensure the client root directory has been created. if not os.path.exists(client_root): os.makedirs(client_root) view_name_git = p4gf_translate.TranslateReponame.repo_to_git(view_name) LOG.debug("_create_p4_client(): view_name_git {0} view_name {1} view_name_p4client {2}". format(view_name_git, view_name ,view_name_p4client)) # If a Git Fusion client for this view already exists, use that, # no need to init the repo. # Do make sure that the client root is correct. if p4gf_util.spec_exists(p4, 'client', client_name): LOG.debug("%s client already exists for %s", client_name, view_name) p4gf_util.ensure_spec_values(p4, 'client', client_name , { 'Root' : client_root , 'Options' : CLIENT_OPTIONS }) return INIT_REPO_EXISTS # Repo config file already checked into Perforce? # Use that. config_path = p4gf_config.depot_path_repo(view_name) config_exists = p4gf_util.depot_file_exists(p4, config_path) if config_exists: return repo_from_config( p4, view_name, client_name, client_root , enable_mismatched_rhs) # Client exist with the same name as this Git Fusion repo? # Build a new config, check it into Perforce, and use that. if not view_name_p4client: view_name_p4client = p4gf_translate.TranslateReponame.git_to_p4client(view_name_git) nop4client = '' if p4gf_util.spec_exists(p4, 'client', view_name_p4client): return repo_from_template_client( p4, view_name, view_name_p4client, client_name , client_root , enable_mismatched_rhs) else: nop4client = _("p4 client '{0}' does not exist\n").format(view_name_p4client) # creating repo from stream? # note that we can't pass '//depot/stream' because git would be confused # but it's ok to pass 'depot/stream' and add the leading '//' here stream_name = '//'+view_name_git if p4gf_util.spec_exists(p4, 'stream', stream_name): return _repo_from_stream(p4, view_name, stream_name, client_name, client_root, enable_mismatched_rhs, handle_imports) # We don't have, and cannot create, a config for this repo. # Say so and give up. msg = p4gf_const.NO_REPO_MSG_TEMPLATE.format(view_name=view_name ,view_name_p4client=view_name_p4client ,nop4client=nop4client) LOG.warn(msg) _print_stderr(msg) return INIT_REPO_NOVIEW
def delete_client(args, p4, client_name, metrics, prune_objs=True): """Delete the named Perforce client and its workspace. Raises P4Exception if the client is not present, or the client configuration is not set up as expected. Keyword arguments: args -- parsed command line arguments p4 -- Git user's Perforce client client_name -- name of client to be deleted metrics -- DeletionMetrics for collecting resulting metrics prune_objs -- if True, delete associated objects from cache """ # pylint: disable=R0912,R0915 group_list = [ p4gf_const.P4GF_GROUP_VIEW_PULL, p4gf_const.P4GF_GROUP_VIEW_PUSH ] p4.user = p4gf_const.P4GF_USER print_verbose(args, _("Checking for client '{}'...").format(client_name)) if not p4gf_util.spec_exists(p4, 'client', client_name): raise P4.P4Exception( _("No such client '{}' defined").format(client_name)) view_name = p4gf_util.client_to_view_name(client_name) p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) p4gf_util.ensure_spec_values(p4, 'client', client_name, {'Root': view_dirs.p4root}) view_lock = None # We're clobbering and deleting. Overrule locks. with p4gf_context.create_context(view_name, view_lock) as ctx: command_path = ctx.client_view_path() homedir = os.path.expanduser('~') raise_if_homedir(homedir, view_name, view_dirs.view_container) # Scan for objects associated only with this view so we can remove them. objects_to_delete = [] if prune_objs: objects_to_delete = _find_client_commit_objects( args, p4, view_name) # Do we have a repo config file to delete? config_file = p4gf_config.depot_path_repo(view_name) + '*' config_file_exists = p4gf_util.depot_file_exists(p4, config_file) # What counters shall we delete? counter_list = [] counter_list.append( p4gf_context.calc_last_copied_change_counter_name( view_name, p4gf_util.get_server_id())) for spec in p4.run('counters', '-u', '-e', "git-fusion-index-last-{},*".format(view_name)): counter_list.append(spec['counter']) for spec in p4.run('counters', '-u', '-e', "git-fusion-index-branch-{},*".format(view_name)): counter_list.append(spec['counter']) if not args.delete: print(NTR('p4 sync -f {}#none').format(command_path)) print(NTR('p4 client -f -d {}').format(client_name)) print(NTR('rm -rf {}').format(view_dirs.view_container)) print( NTR('Deleting {} objects from //{}/objects/...').format( len(objects_to_delete), p4gf_const.P4GF_DEPOT)) for group_template in group_list: group = group_template.format(view=view_name) print(NTR('p4 group -a -d {}').format(group)) for c in counter_list: print(NTR('p4 counter -u -d {}').format(c)) if config_file_exists: print(NTR('p4 sync -f {}').format(config_file)) print(NTR('p4 delete {}').format(config_file)) print( NTR('p4 submit -d "Delete repo config for {view_name}" {config_file}' ).format(view_name=view_name, config_file=config_file)) else: print_verbose( args, NTR('Removing client files for {}...').format(client_name)) ctx.p4.run('sync', '-fq', command_path + '#none') print_verbose(args, NTR('Deleting client {}...').format(client_name)) p4.run('client', '-df', client_name) metrics.clients += 1 print_verbose( args, NTR("Deleting repo {0}'s directory {1}...").format( view_name, view_dirs.view_container)) _remove_tree(view_dirs.view_container, contents_only=False) metrics.files += _delete_files(p4, objects_to_delete, view_name) for group_template in group_list: _delete_group(args, p4, group_template.format(view=view_name), metrics) for c in counter_list: _delete_counter(p4, c, metrics) if config_file_exists: p4gf_util.p4run_logged(p4, ['sync', '-fq', config_file]) with p4gf_util.NumberedChangelist( p4=p4, description=_("Delete repo config for '{}'").format( view_name)) as nc: nc.p4run(["delete", config_file]) nc.submit()
def delete_client(args, p4, client_name, metrics, prune_objs=True): """Delete the named Perforce client and its workspace. Raises P4Exception if the client is not present, or the client configuration is not set up as expected. Keyword arguments: args -- parsed command line arguments p4 -- Git user's Perforce client client_name -- name of client to be deleted metrics -- DeletionMetrics for collecting resulting metrics prune_objs -- if True, delete associated objects from cache """ # pylint: disable=R0912,R0915 group_list = [p4gf_const.P4GF_GROUP_VIEW_PULL, p4gf_const.P4GF_GROUP_VIEW_PUSH] p4.user = p4gf_const.P4GF_USER print_verbose(args, _("Checking for client '{}'...").format(client_name)) if not p4gf_util.spec_exists(p4, 'client', client_name): raise P4.P4Exception(_("No such client '{}' defined") .format(client_name)) view_name = p4gf_util.client_to_view_name(client_name) p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) p4gf_util.ensure_spec_values(p4, 'client', client_name, {'Root': view_dirs.p4root}) view_lock = None # We're clobbering and deleting. Overrule locks. with p4gf_context.create_context(view_name, view_lock) as ctx: command_path = ctx.client_view_path() homedir = os.path.expanduser('~') raise_if_homedir(homedir, view_name, view_dirs.view_container) # Scan for objects associated only with this view so we can remove them. objects_to_delete = [] if prune_objs: objects_to_delete = _find_client_commit_objects(args, p4, view_name) # Do we have a repo config file to delete? config_file = p4gf_config.depot_path_repo(view_name) + '*' config_file_exists = p4gf_util.depot_file_exists(p4, config_file) # What counters shall we delete? counter_list = [] counter_list.append(p4gf_context.calc_last_copied_change_counter_name( view_name, p4gf_util.get_server_id())) for spec in p4.run('counters', '-u', '-e', "git-fusion-index-last-{},*" .format(view_name)): counter_list.append(spec['counter']) for spec in p4.run('counters', '-u', '-e', "git-fusion-index-branch-{},*" .format(view_name)): counter_list.append(spec['counter']) if not args.delete: print(NTR('p4 sync -f {}#none').format(command_path)) print(NTR('p4 client -f -d {}').format(client_name)) print(NTR('rm -rf {}').format(view_dirs.view_container)) print(NTR('Deleting {} objects from //{}/objects/...').format( len(objects_to_delete), p4gf_const.P4GF_DEPOT)) for group_template in group_list: group = group_template.format(view=view_name) print(NTR('p4 group -a -d {}').format(group)) for c in counter_list: print(NTR('p4 counter -u -d {}').format(c)) if config_file_exists: print(NTR('p4 sync -f {}').format(config_file)) print(NTR('p4 delete {}').format(config_file)) print(NTR('p4 submit -d "Delete repo config for {view_name}" {config_file}') .format(view_name=view_name, config_file=config_file)) else: print_verbose(args, NTR('Removing client files for {}...').format(client_name)) ctx.p4.run('sync', '-fq', command_path + '#none') print_verbose(args, NTR('Deleting client {}...').format(client_name)) p4.run('client', '-df', client_name) metrics.clients += 1 print_verbose(args, NTR("Deleting repo {0}'s directory {1}...").format(view_name, view_dirs.view_container)) _remove_tree(view_dirs.view_container, contents_only=False) metrics.files += _delete_files(p4, objects_to_delete, view_name) for group_template in group_list: _delete_group(args, p4, group_template.format(view=view_name), metrics) for c in counter_list: _delete_counter(p4, c, metrics) if config_file_exists: p4gf_util.p4run_logged(p4, ['sync', '-fq', config_file]) with p4gf_util.NumberedChangelist( p4=p4, description=_("Delete repo config for '{}'") .format(view_name)) as nc: nc.p4run(["delete", config_file]) nc.submit()
def _create_p4_client(p4, view_name, client_name, client_root, enable_mismatched_rhs, view_name_p4client, handle_imports=True): """Create the p4 client to contain Git meta-data mirror. Keyword arguments: p4 -- Perforce client API view_name -- client view of repository to clone - internal (translated) viewname client_name -- client that will be created client_root -- path for client workspace enable_mismatched_rhs -- allow branches to have differing RHS? view_name_p4client -- name of actual p4 client on which to base this new repo if None - will be determined from view_name if needed Returns one of the INIT_REPO_* constants. """ # Ensure the client root directory has been created. if not os.path.exists(client_root): os.makedirs(client_root) view_name_git = p4gf_translate.TranslateReponame.repo_to_git(view_name) LOG.debug( "_create_p4_client(): view_name_git {0} view_name {1} view_name_p4client {2}" .format(view_name_git, view_name, view_name_p4client)) # If a Git Fusion client for this view already exists, use that, # no need to init the repo. # Do make sure that the client root is correct. if p4gf_util.spec_exists(p4, 'client', client_name): LOG.debug("%s client already exists for %s", client_name, view_name) p4gf_util.ensure_spec_values(p4, 'client', client_name, { 'Root': client_root, 'Options': CLIENT_OPTIONS }) return INIT_REPO_EXISTS # Repo config file already checked into Perforce? # Use that. config_path = p4gf_config.depot_path_repo(view_name) config_exists = p4gf_util.depot_file_exists(p4, config_path) if config_exists: return repo_from_config(p4, view_name, client_name, client_root, enable_mismatched_rhs) # Client exist with the same name as this Git Fusion repo? # Build a new config, check it into Perforce, and use that. if not view_name_p4client: view_name_p4client = p4gf_translate.TranslateReponame.git_to_p4client( view_name_git) nop4client = '' if p4gf_util.spec_exists(p4, 'client', view_name_p4client): return repo_from_template_client(p4, view_name, view_name_p4client, client_name, client_root, enable_mismatched_rhs) else: nop4client = _("p4 client '{0}' does not exist\n").format( view_name_p4client) # creating repo from stream? # note that we can't pass '//depot/stream' because git would be confused # but it's ok to pass 'depot/stream' and add the leading '//' here stream_name = '//' + view_name_git if p4gf_util.spec_exists(p4, 'stream', stream_name): return _repo_from_stream(p4, view_name, stream_name, client_name, client_root, enable_mismatched_rhs, handle_imports) # We don't have, and cannot create, a config for this repo. # Say so and give up. msg = p4gf_const.NO_REPO_MSG_TEMPLATE.format( view_name=view_name, view_name_p4client=view_name_p4client, nop4client=nop4client) LOG.warn(msg) _print_stderr(msg) return INIT_REPO_NOVIEW
def _repo_config_exists(p4, repo_name): """Return true is repo p4gf_config exists.""" config_path = p4gf_config.depot_path_repo(repo_name) return p4gf_util.depot_file_exists(p4, config_path)