def reset_git_enviro(): """Clear GIT_DIR and other GIT_xxx environment variables, then chdir to GIT_WORK_TREE. This undoes any strangeness that might come in from T4 calling 'git --git-dir=xxx --work-tree=yyy' which might cause us to erroneously operate on the "client-side" git repo when invoked from T4. or from git-receive-pack chdir-ing into the .git dir. """ git_env_key = [k for k in os.environ if k.startswith("GIT_")] for key in git_env_key: del os.environ[key] # Find our view name, use that to calculate and chdir into our GIT_WORK_TREE. rc_path = p4gf_path.cwd_to_rc_file() if (rc_path): view_name = rc_path_to_view_name(rc_path) LOG.debug("reset_git_enviro rc_path_to_view_name({rc_path}) returned {view_name}" .format(rc_path=rc_path, view_name=view_name)) p4gf_dir = rc_path_to_p4gf_dir(rc_path) LOG.debug("reset_git_enviro rc_path_to_p4gf_dir({rc_path}) returned {p4gf_dir}" .format(rc_path=rc_path, p4gf_dir=p4gf_dir)) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) os.chdir(view_dirs.GIT_WORK_TREE)
def reset_git_enviro(): """Clear GIT_DIR and other GIT_xxx environment variables, then chdir to GIT_WORK_TREE. This undoes any strangeness that might come in from T4 calling 'git --git-dir=xxx --work-tree=yyy' which might cause us to erroneously operate on the "client-side" git repo when invoked from T4. or from git-receive-pack chdir-ing into the .git dir. """ git_env_key = [k for k in os.environ if k.startswith("GIT_")] for key in git_env_key: del os.environ[key] # Find our view name, use that to calculate and chdir into our GIT_WORK_TREE. rc_path = p4gf_path.cwd_to_rc_file() if (rc_path): view_name = rc_path_to_view_name(rc_path) LOG.debug( "reset_git_enviro rc_path_to_view_name({rc_path}) returned {view_name}" .format(rc_path=rc_path, view_name=view_name)) p4gf_dir = rc_path_to_p4gf_dir(rc_path) LOG.debug( "reset_git_enviro rc_path_to_p4gf_dir({rc_path}) returned {p4gf_dir}" .format(rc_path=rc_path, p4gf_dir=p4gf_dir)) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) os.chdir(view_dirs.GIT_WORK_TREE)
def __set_up_paths(self): """set up depot and local paths for both content and P4GF These paths are derived from the client root and client view. """ self.__set_up_content_paths() self.__set_up_p4gf_paths() self.view_dirs = p4gf_view_dirs.from_p4gf_dir(self.gitrootdir, self.config.view_name)
def init_repo(p4, view_name, view_lock, charset=None, enable_mismatched_rhs=False, view_name_p4client=None, handle_imports=True): ''' Create view and repo if necessary. Does NOT copy p4 to the repo (that's p4gf_copy_p2g's job). Returns one of the INIT_REPO_* constants. This is p4gf_auth_server's entry point into init_repo, called in response to a 'git clone'. view_name is the internal view_name with special chars already translated view_lock CounterLock mutex that prevents other processes from touching this repo, whether on this Git Fusion server or another. ''' LOG.debug("init_repo : view_name {1} view_name_p4client {1}".format( view_name, view_name_p4client)) client_name = p4gf_util.view_to_client_name(view_name) p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) result = _create_p4_client(p4, view_name, client_name, view_dirs.p4root, enable_mismatched_rhs, view_name_p4client, handle_imports) if result > INIT_REPO_OK: return result create_perm_groups(p4, view_name) with p4gf_context.create_context(view_name, view_lock) as ctx: p4gf_config.create_file_repo(ctx, view_name, charset) if ctx.client_exclusions_added: _print_stderr( _("The referenced client view contains implicit exclusions." "\nThe Git Fusion config will contain these as explicit exclusions." )) p4gf_copy_p2g.create_git_repo(ctx, view_dirs.GIT_DIR) create_p4_client_root(view_dirs.p4root) p4gf_rc.update_file(view_dirs.rcfile, client_name, view_name) if result == INIT_REPO_OK: LOG.debug("repository creation for %s complete", view_name) # return the result of creating the client, to indicate if the client # had already been set up or not return result
def copy_p2g_ctx(ctx, start=None): """Using the given context, copy its view from Perforce to Git. Common code for p4gf_auth_server.py and p4gf_init_repo.py for setting up the eventual call to copy_p2g.""" view_name = ctx.config.view_name # Find directory paths to feed to git. p4gf_dir = p4gf_util.p4_to_p4gf_dir(ctx.p4gf) ctx.view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) # cd into the work directory. Not all git functions react well to --work-tree=xxxx. os.chdir(ctx.view_dirs.GIT_WORK_TREE) # Fill git with content from Perforce. copy_p2g(ctx, start)
def _list_for_server(): ''' Return list of repos that have been copied to the given Git Fusion server. "have been copied" here means "has a .git-fusion/views/<view_name>/ directory on this server." ''' p4 = p4gf_create_p4.create_p4(client=p4gf_util.get_object_client_name()) result = [] p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) for view_name in p4gf_util.view_list(p4): view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) if os.path.exists(view_dirs.GIT_DIR): result.append(view_name) p4gf_create_p4.destroy(p4) return result
def init_repo(p4 , view_name , view_lock , charset=None , enable_mismatched_rhs=False , view_name_p4client=None , handle_imports=True): ''' Create view and repo if necessary. Does NOT copy p4 to the repo (that's p4gf_copy_p2g's job). Returns one of the INIT_REPO_* constants. This is p4gf_auth_server's entry point into init_repo, called in response to a 'git clone'. view_name is the internal view_name with special chars already translated view_lock CounterLock mutex that prevents other processes from touching this repo, whether on this Git Fusion server or another. ''' LOG.debug("init_repo : view_name {1} view_name_p4client {1}".format( view_name, view_name_p4client)) client_name = p4gf_util.view_to_client_name(view_name) p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) result = _create_p4_client(p4, view_name, client_name, view_dirs.p4root, enable_mismatched_rhs, view_name_p4client, handle_imports) if result > INIT_REPO_OK: return result create_perm_groups(p4, view_name) with p4gf_context.create_context(view_name, view_lock) as ctx: p4gf_config.create_file_repo(ctx, view_name, charset) if ctx.client_exclusions_added: _print_stderr(_("The referenced client view contains implicit exclusions." "\nThe Git Fusion config will contain these as explicit exclusions.")) p4gf_copy_p2g.create_git_repo(ctx, view_dirs.GIT_DIR) create_p4_client_root(view_dirs.p4root) p4gf_rc.update_file(view_dirs.rcfile, client_name, view_name) if result == INIT_REPO_OK: LOG.debug("repository creation for %s complete", view_name) # return the result of creating the client, to indicate if the client # had already been set up or not return result
def cleanup_client(ctx, view_name): """Clean up the failed client and workspace after an error occurs while creating the initial clone. If the client does not exist, nothing is done. """ client_name = p4gf_const.P4GF_CLIENT_PREFIX + view_name if not p4gf_util.spec_exists(ctx.p4, 'client', client_name): return LOG.debug('cleaning up failed view {}'.format(view_name)) command_path = ctx.client_view_path() p4gf_dir = p4gf_util.p4_to_p4gf_dir(ctx.p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) ctx.p4.run('sync', '-fq', command_path + '#none') ctx.p4.run('client', '-df', client_name) for vdir in [view_dirs.view_container]: LOG.debug('removing view directory {}'.format(vdir)) if os.path.isdir(vdir): shutil.rmtree(vdir) elif os.path.isfile(vdir): os.remove(vdir)
def init_repo(p4, view_name): """Create view and repo if necessary. Does NOT copy p4 to the repo (that's p4gf_copy_p2g's job). Returns one of the INIT_REPO_* constants. """ client_name = p4gf_context.view_to_client_name(view_name) p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) result = create_p4_client(p4, view_name, client_name, view_dirs.p4root) if result > INIT_REPO_OK: return result create_perm_groups(p4, view_name) p4gf_copy_p2g.create_git_repo(view_dirs.GIT_DIR) ensure_deny_rewind(view_dirs.GIT_WORK_TREE) install_hook(view_dirs.GIT_DIR) create_p4_client_root(view_dirs.p4root) p4gf_rc.update_file(view_dirs.rcfile, client_name, view_name) LOG.debug("repository creation for %s complete", view_name) # return the result of creating the client, to indicate if the client # had already been set up or not return result
def delete_client(args, p4, client_name): """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 """ 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 = client_name[len(p4gf_const.P4GF_CLIENT_PREFIX):] view_lock = None # We're clobbering and deleting. Overrule locks. try: ctx = p4gf_context.create_context(view_name, view_lock) except RuntimeError: # not a conforming Git Fusion client, ignore it return command_path = ctx.client_view_path() p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) rm_list = [view_dirs.view_container] homedir = os.path.expanduser('~') raise_if_homedir(homedir, view_name, rm_list) # Scan for objects associated only with this view so we can either remove # them completely or update their 'views' attribute appropriately. p4.handler = FilterViewFstatHandler(view_name) p4.run("fstat", "-Oa", "-T", "depotFile, attr-views", "//.git-fusion/objects/...") objects_to_delete = p4.handler.files_to_delete objects_to_modify = p4.handler.files_to_modify p4.handler = None if not args.delete: print("p4 sync -f {}#none".format(command_path)) print("p4 client -f -d {}".format(client_name)) for d in rm_list: print("rm -rf {}".format(d)) for to_delete in objects_to_delete: print("p4 obliterate -y {}".format(to_delete)) if objects_to_modify: for (fname, views) in objects_to_modify: print("attribute -p -n views -v {} {}".format(views, fname)) for group_template in group_list: group = group_template.format(view=view_name) print("p4 group -a -d {}".format(group)) print('p4 counter -u -d {}'.format( p4gf_lock.view_lock_name(view_name))) else: print_verbose(args, "Removing client files for {}...".format(client_name)) ctx.p4.run('sync', '-fq', command_path + '#none') print_verbose(args, "Deleting client {}...".format(client_name)) p4.run('client', '-df', client_name) for d in rm_list: remove_file_or_dir(args, view_name, d) bite_size = 1000 while len(objects_to_delete): to_delete = objects_to_delete[:bite_size] objects_to_delete = objects_to_delete[bite_size:] p4.run("obliterate", "-y", to_delete) if objects_to_modify: for (fname, views) in objects_to_modify: p4.run("edit", fname) p4.run("attribute", "-p", "-n", "views", "-v", views, fname) p4.run("submit", "-d", "'Removing {} from views attribute'".format(view_name)) for group_template in group_list: delete_group(args, p4, group_template.format(view=view_name)) _delete_counter(p4, p4gf_lock.view_lock_name(view_name))
def main(): """set up repo for a view""" with ExceptionAuditLogger(): args = parse_args(sys.argv[1:]) if not args: return 1 # Record the p4 user in environment. We use environment to pass to # git-invoked hook. We don't have to set ctx.authenticated_p4user because # Context.__init__() reads it from environment, which we set here. os.environ[p4gf_const.P4GF_AUTH_P4USER_ENVAR] = args.user # print "args={}".format(args) view_name = args.options[-1] p4gf_util.reset_git_enviro() p4 = connect_p4() if not p4: return 2 LOG.debug("connected to P4: %s", p4) _check_lock_perm(p4) if not check_protects(p4): _raise_p4gf_perm() if run_special_command(view_name, p4, args.user): return 0 # Go no further, create NOTHING, if user not authorized. view_perm = p4gf_group.ViewPerm.for_user_and_view( p4, args.user, view_name) _check_authorization(view_perm, args.user, args.command[0], view_name) # Create Git Fusion server depot, user, config. NOPs if already created. p4gf_init.init(p4) with p4gf_lock.view_lock(p4, view_name) as view_lock: # Create Git Fusion per-repo client view mapping and config. # # NOPs if already created. # Create the empty directory that will hold the git repo. init_repo_status = p4gf_init_repo.init_repo(p4, view_name) if init_repo_status == p4gf_init_repo.INIT_REPO_OK: repo_created = True elif init_repo_status == p4gf_init_repo.INIT_REPO_EXISTS: repo_created = False else: return 1 # If authorization came from default, not explicit group # membership, copy that authorization to a group now. Could # not do this until after p4gf_init_repo() has a chance to # create not-yet-existing groups. view_perm.write_if(p4) # Now that we have valid git-fusion-user and # git-fusion-<view> client, replace our temporary P4 # connection with a more permanent Context, shared for the # remainder of this process. ctx = p4gf_context.create_context(view_name, view_lock) del p4 LOG.debug("reconnected to P4, p4gf=%s", ctx.p4gf) # Find directory paths to feed to git. ctx.view_dirs = p4gf_view_dirs.from_p4gf_dir( ctx.gitrootdir, view_name) ctx.log_context() # cd into the work directory. Not all git functions react well # to --work-tree=xxxx. cwd = os.getcwd() os.chdir(ctx.view_dirs.GIT_WORK_TREE) # Copy any recent changes from Perforce to Git. try: p4gf_copy_p2g.copy_p2g_ctx(ctx) except: # Dump failure to log, BEFORE cleanup, just in case # cleanup ALSO fails and throws its own error (which # happens if we're out of memory). LOG.error(traceback.format_exc()) if repo_created: # Return to the original working directory to allow the # config code to call os.getcwd() without dying, since # we are about to delete the current working directory. os.chdir(cwd) cleanup_client(ctx, view_name) raise # Detach git repo's workspace from master before calling # original git, otherwise we won't be able to push master. p4gf_util.checkout_detached_master() # Flush stderr before returning control to Git. # Otherwise Git's own output might interrupt ours. sys.stderr.flush() return _call_original_git(ctx, args)
def delete_client(args, p4, client_name): """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 """ 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 = client_name[len(p4gf_const.P4GF_CLIENT_PREFIX):] view_lock = None # We're clobbering and deleting. Overrule locks. try: ctx = p4gf_context.create_context(view_name, view_lock) except RuntimeError: # not a conforming Git Fusion client, ignore it return command_path = ctx.client_view_path() p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4) view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name) rm_list = [view_dirs.view_container] homedir = os.path.expanduser('~') raise_if_homedir(homedir, view_name, rm_list) # Scan for objects associated only with this view so we can either remove # them completely or update their 'views' attribute appropriately. p4.handler = FilterViewFstatHandler(view_name) p4.run("fstat", "-Oa", "-T", "depotFile, attr-views", "//.git-fusion/objects/...") objects_to_delete = p4.handler.files_to_delete objects_to_modify = p4.handler.files_to_modify p4.handler = None if not args.delete: print("p4 sync -f {}#none".format(command_path)) print("p4 client -f -d {}".format(client_name)) for d in rm_list: print("rm -rf {}".format(d)) for to_delete in objects_to_delete: print("p4 obliterate -y {}".format(to_delete)) if objects_to_modify: for (fname, views) in objects_to_modify: print("attribute -p -n views -v {} {}".format(views, fname)) for group_template in group_list: group = group_template.format(view=view_name) print("p4 group -a -d {}".format(group)) print('p4 counter -u -d {}'.format(p4gf_lock.view_lock_name(view_name))) else: print_verbose(args, "Removing client files for {}...".format(client_name)) ctx.p4.run('sync', '-fq', command_path + '#none') print_verbose(args, "Deleting client {}...".format(client_name)) p4.run('client', '-df', client_name) for d in rm_list: remove_file_or_dir(args, view_name, d) bite_size = 1000 while len(objects_to_delete): to_delete = objects_to_delete[:bite_size] objects_to_delete = objects_to_delete[bite_size:] p4.run("obliterate", "-y", to_delete) if objects_to_modify: for (fname, views) in objects_to_modify: p4.run("edit", fname) p4.run("attribute", "-p", "-n", "views", "-v", views, fname) p4.run("submit", "-d", "'Removing {} from views attribute'".format(view_name)) for group_template in group_list: delete_group(args, p4, group_template.format(view=view_name)) _delete_counter(p4, p4gf_lock.view_lock_name(view_name))
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 main(): """set up repo for a view""" with ExceptionAuditLogger(): args = parse_args(sys.argv[1:]) if not args: return 1 # Record the p4 user in environment. We use environment to pass to # git-invoked hook. We don't have to set ctx.authenticated_p4user because # Context.__init__() reads it from environment, which we set here. os.environ[p4gf_const.P4GF_AUTH_P4USER_ENVAR] = args.user # print "args={}".format(args) view_name = args.options[-1] p4gf_util.reset_git_enviro() p4 = connect_p4() if not p4: return 2 LOG.debug("connected to P4: %s", p4) _check_lock_perm(p4) if not check_protects(p4): _raise_p4gf_perm() if run_special_command(view_name, p4, args.user): return 0 # Go no further, create NOTHING, if user not authorized. view_perm = p4gf_group.ViewPerm.for_user_and_view(p4, args.user, view_name) _check_authorization(view_perm, args.user, args.command[0], view_name) # Create Git Fusion server depot, user, config. NOPs if already created. p4gf_init.init(p4) with p4gf_lock.view_lock(p4, view_name) as view_lock: # Create Git Fusion per-repo client view mapping and config. # # NOPs if already created. # Create the empty directory that will hold the git repo. init_repo_status = p4gf_init_repo.init_repo(p4, view_name) if init_repo_status == p4gf_init_repo.INIT_REPO_OK: repo_created = True elif init_repo_status == p4gf_init_repo.INIT_REPO_EXISTS: repo_created = False else: return 1 # If authorization came from default, not explicit group # membership, copy that authorization to a group now. Could # not do this until after p4gf_init_repo() has a chance to # create not-yet-existing groups. view_perm.write_if(p4) # Now that we have valid git-fusion-user and # git-fusion-<view> client, replace our temporary P4 # connection with a more permanent Context, shared for the # remainder of this process. ctx = p4gf_context.create_context(view_name, view_lock) del p4 LOG.debug("reconnected to P4, p4gf=%s", ctx.p4gf) # Find directory paths to feed to git. ctx.view_dirs = p4gf_view_dirs.from_p4gf_dir(ctx.gitrootdir, view_name) ctx.log_context() # cd into the work directory. Not all git functions react well # to --work-tree=xxxx. cwd = os.getcwd() os.chdir(ctx.view_dirs.GIT_WORK_TREE) # Copy any recent changes from Perforce to Git. try: p4gf_copy_p2g.copy_p2g_ctx(ctx) except: # Dump failure to log, BEFORE cleanup, just in case # cleanup ALSO fails and throws its own error (which # happens if we're out of memory). LOG.error(traceback.format_exc()) if repo_created: # Return to the original working directory to allow the # config code to call os.getcwd() without dying, since # we are about to delete the current working directory. os.chdir(cwd) cleanup_client(ctx, view_name) raise # Detach git repo's workspace from master before calling # original git, otherwise we won't be able to push master. p4gf_util.checkout_detached_master() # Flush stderr before returning control to Git. # Otherwise Git's own output might interrupt ours. sys.stderr.flush() return _call_original_git(ctx, args)