def convert_view_from_no_client_name(view, new_client_name): ''' Convert a view mapping's right-hand-side from its original client name to a new client name: //depot/dir/... dir/... //depot/durr/... durr/... becomes //depot/dir/... //client/dir/... //depot/durr/... //client/durr/... Accepts view as P4.Map, str. or list. Returns view as P4.Map(). ''' if isinstance(view, P4.Map): old_map = view elif isinstance(view, str): view_lines = view.splitlines() old_map = P4.Map(view_lines) else: view_lines = view old_map = P4.Map(view_lines) lhs = old_map.lhs() new_prefix = '//{}/'.format(new_client_name) rhs = [new_prefix + p4gf_path.dequote(r) for r in old_map.rhs()] new_map = P4.Map() for (l, r) in zip(lhs, rhs): new_map.insert(l, r) return new_map
def replace_client_name(view, old_client_name, new_client_name): ''' Convert "//depot/... //old_client/..." to "//depot/... //new_client" Accepts view as P4.Map, str. or list. Returns view as P4.Map(). ''' if isinstance(view, P4.Map): old_map = view elif isinstance(view, str): view_lines = view.splitlines() old_map = P4.Map(view_lines) else: view_lines = view old_map = P4.Map(view_lines) lhs = old_map.lhs() new_prefix = '//{}/'.format(new_client_name) old_prefix = '//{}/'.format(old_client_name) old_len = len(old_prefix) rhs = [new_prefix + p4gf_path.dequote(r)[old_len:] for r in old_map.rhs()] new_map = P4.Map() for (l, r) in zip(lhs, rhs): new_map.insert(l, r) return new_map
def _map_inclusion_can_bypass_files(mapapi): """Do any of the map's lines contain wildcards other than terminal ... ? Any exclusions? The optimization code can reliable tell if every file in //depot/a/... is within //depot/..., but cannot reliable tell if //depot/a/... is within //depot/*x or depot/*/foo/... . Yes it is possible to enhance the optimization code to reliable deal with a few more mapping permutations, but trailing ... is the biggest benefit for the least complexity. """ for line in mapapi.lhs(): line = dequote(line) # Exclusion? if line.startswith('-'): return False # Trailing dot-dot-dot expected, supported. # Remove so it does not trigger rejection. if line.endswith('...'): line = line[:-3] # Any other wildcard? Going to have to run 'p4 files'. Sorry. for wild in WILDCARDS: if wild in line: return False return True
def find_depot_branch(self, ctx): ''' Scan through known DepotBranchInfo until we find one whose root contains the first line of our view. ''' lhs0 = p4gf_path.dequote(self.view_p4map.lhs()[0]) depot_branch = ctx.depot_branch_info_index().find_depot_path(lhs0) return depot_branch
def map_includes_entire_view(mapapi, view_list): """Can we tell if the view is completely included in the map? +++ This is a big optimization when it works: if we can determine COMPLETELY_INCLUED or COMPLETELY_EXCLUDED, there is no need to run 'p4 files //<client>/...' to check each file path against protects. COMPLETELY_INCLUDED : view is completely included, no exclusions or omissions make it possible for any path in view to be excluded. COMPLETELY_EXCLUDED : view does not overlap mapapi at all. No path in view can be included. UNKNOWN : exclusions, partial overlap, or wildcards other than terminal ... make it impossible to tell from just a view list whether all of the views _current_ files are included in the mapapi. Must run 'p4 -c <client> files //<client>/...' and pump each returned file path through mapapi to test for inclusion. """ view_mapapi = P4.Map(view_list) if (not _map_inclusion_can_bypass_files(mapapi) or not _map_inclusion_can_bypass_files(view_mapapi)): return UNKNOWN included = [] excluded = [] for line in view_mapapi.lhs(): line = dequote(line) if mapapi.includes(line): included.append(line) else: excluded.append(line) if included and not excluded: return COMPLETELY_INCLUDED if not included and excluded: return COMPLETELY_EXCLUDED return UNKNOWN
def map_includes_entire_view(mapapi, view_list): """Can we tell if the view is completely included in the map? +++ This is a big optimization when it works: if we can determine COMPLETELY_INCLUED or COMPLETELY_EXCLUDED, there is no need to run 'p4 files //<client>/...' to check each file path against protects. COMPLETELY_INCLUDED : view is completely included, no exclusions or omissions make it possible for any path in view to be excluded. COMPLETELY_EXCLUDED : view does not overlap mapapi at all. No path in view can be included. UNKNOWN : exclusions, partial overlap, or wildcards other than terminal ... make it impossible to tell from just a view list whether all of the views _current_ files are included in the mapapi. Must run 'p4 -c <client> files //<client>/...' and pump each returned file path through mapapi to test for inclusion. """ view_mapapi = P4.Map(view_list) if ( not _map_inclusion_can_bypass_files(mapapi) or not _map_inclusion_can_bypass_files(view_mapapi)): return UNKNOWN included = [] excluded = [] for line in view_mapapi.lhs(): line = dequote(line) if mapapi.includes(line): included.append(line) else: excluded.append(line) if included and not excluded: return COMPLETELY_INCLUDED if not included and excluded: return COMPLETELY_EXCLUDED return UNKNOWN
def _read_user_map(self): """Read the user map file from Perforce into a list of tuples. Tuples consist of username, email address, and full name. If no such file exists, return an empty list. Return a list of 3-tuples: (p4user, email, fullname) """ usermap = [] all_existing_mapped_users = {} # value True indicates standard type mappath = p4gf_const.P4GF_HOME + '/users/p4gf_usermap' global _user_map_synced if not _user_map_synced: # don't let a writable usermap file get in our way self.p4.run('sync', '-fq', mappath) _user_map_synced = True if not os.path.exists(mappath): return usermap with open(mappath) as mf: no_folding = self._is_case_sensitive() for line in mf: if not line: continue line = line.strip() if not line or line[0] == '#': continue m = USERMAP_REGEX.search(line) if not m: LOG.debug('No match: {}'.format(line)) continue p4user = m.group(1) if no_folding else m.group(1).casefold() email = m.group(2) _validate_email(email) fullname = p4gf_path.dequote(m.group(3)) # Do not load a usermap for P4GF_USER - git-fusion-user if p4user == p4gf_const.P4GF_USER: LOG.warning( "{0} user disallowed in usermap. Skipping: {1}".format( p4gf_const.P4GF_USER, line)) continue # Disallow any mapped existing users which are not of standard type if p4user in all_existing_mapped_users: if not all_existing_mapped_users[p4user]: LOG.warning( "non standard user {0} disallowed in usermap. " "Skipping: {1}".format(p4user, line)) continue else: if p4gf_p4spec.spec_exists(self.p4, 'user', p4user): all_existing_mapped_users[ p4user] = p4gf_p4spec.spec_values_match( self.p4, 'user', p4user, {'Type': 'standard'}) if not all_existing_mapped_users[p4user]: LOG.warning( "non standard user {0} disallowed in usermap. " "Skipping: {1}".format(p4user, line)) continue usermap.append((p4user, email, fullname)) return usermap