def main(): """ Parses the command line arguments and performs a search for the given email address in the user map. """ p4gf_util.has_server_id_or_exit() log_l10n() # Set up argument parsing. parser = p4gf_util.create_arg_parser( _("Searches for an email address in the user map.")) parser.add_argument(NTR('email'), metavar='E', help=_('email address to find')) args = parser.parse_args() # make sure the world is sane ec = p4gf_init.main() if ec: print(_("p4gf_usermap initialization failed")) sys.exit(ec) with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4(client=p4gf_util.get_object_client_name()) if not p4: sys.exit(1) usermap = UserMap(p4) user = usermap.lookup_by_email(args.email) if user: print(_("Found user '{}' <{}>").format(user[0], user[2])) sys.exit(0) else: sys.stderr.write(_("No such user found: '{}'\n").format(args.email)) sys.exit(1)
def main(): ''' Parse the command-line arguments and print a configuration. ''' p4gf_util.has_server_id_or_exit() p4gf_client = p4gf_util.get_object_client_name() p4 = p4gf_create_p4.create_p4(client=p4gf_client) if not p4: sys.exit(1) desc = _("""Display the effective global or repository configuration. All comment lines are elided and formatting is normalized per the default behavior of the configparser Python module. The default configuration options will be produced if either of the configuration files is missing. """) parser = p4gf_util.create_arg_parser(desc=desc) parser.add_argument(NTR('repo'), metavar=NTR('R'), nargs='?', default='', help=_('name of the repository, or none to display global.')) args = parser.parse_args() if args.repo: cfg = get_repo(p4, args.repo) else: cfg = get_global(p4) if not cfg: print(_('Unable to read configuration file!')) cfg.write(sys.stdout)
def main(): ''' Parse the command-line arguments and print a configuration. ''' p4gf_util.has_server_id_or_exit() p4gf_client = p4gf_util.get_object_client_name() p4 = p4gf_create_p4.create_p4(client=p4gf_client) if not p4: sys.exit(1) desc = _("""Display the effective global or repository configuration. All comment lines are elided and formatting is normalized per the default behavior of the configparser Python module. The default configuration options will be produced if either of the configuration files is missing. """) parser = p4gf_util.create_arg_parser(desc=desc) parser.add_argument( NTR('repo'), metavar=NTR('R'), nargs='?', default='', help=_('name of the repository, or none to display global.')) args = parser.parse_args() if args.repo: cfg = get_repo(p4, args.repo) else: cfg = get_global(p4) if not cfg: print(_('Unable to read configuration file!')) cfg.write(sys.stdout)
def check_readiness(p4): """ Check that P4GF is ready for accepting connections from clients. """ # Note the "clever" use of counter names with a shared prefix that # just happen to be the two counters we are interested in retrieving. # (wanted to avoid another call to p4 counter, but without retrieving # _all_ P4GF counters, which could be millions). fetch_counters = lambda p4: p4.run('counters', '-u', '-e', 'git-fusion-pre*') if p4.connected(): counters = fetch_counters(p4) else: with p4gf_create_p4.p4_connect(p4): counters = fetch_counters(p4) # Check if the "prevent further access" counter has been set, and raise an # error if the counter is anything other than zero. value = fetch_counter_value(counters, p4gf_const.P4GF_COUNTER_PREVENT_NEW_SESSIONS) if value and value != '0': raise RuntimeError(_('Git Fusion is shutting down. Please contact your admin.')) # Check that GF submit trigger is installed and has a compatible version. value = fetch_counter_value(counters, p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION) trigger_version_counter = value.split(":")[0].strip() if value else '0' if int(trigger_version_counter) != int(p4gf_const.P4GF_TRIGGER_VERSION): LOG.error("Incompatible trigger version: {0} should be {1} but got {2}".format( p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION, p4gf_const.P4GF_TRIGGER_VERSION, trigger_version_counter)) if int(trigger_version_counter) == 0: raise RuntimeError(_('Git Fusion submit triggers are not installed.' ' Please contact your admin.')) else: raise RuntimeError(_('Git Fusion submit triggers need updating.' ' Please contact your admin.')) p4gf_util.has_server_id_or_exit(log=LOG)
def main(): """Create Perforce user and client for Git Fusion.""" p4gf_version_3.log_version_extended(include_checksum=True) try: log_l10n() p4gf_version_3.version_check() except Exception as e: # pylint: disable=broad-except sys.stderr.write(e.args[0] + '\n') sys.exit(1) # To fetch the object client below we need to ensure there is a server # ID available on this system, and since we require that anyway, may as # well check it now, when we need it. p4gf_util.has_server_id_or_exit() with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4_temp_client() if not p4: return 2 Verbosity.report(Verbosity.INFO, "P4PORT : {}".format(p4.port)) Verbosity.report(Verbosity.INFO, "P4USER : {}".format(p4.user)) p4gf_util.reset_git_enviro() p4gf_proc.init() try: init(p4) remove_old_temp_and_repo_clients(p4) except PermissionError: LOG.exception("unable to initialize Git Fusion") sys.stderr.write(_("File permissions error, please check ownership" " and mode of ~/.git-fusion directory.\n")) sys.exit(os.EX_NOPERM) return 0
def main(): """Set up repo for a view.""" p4gf_util.has_server_id_or_exit() args = _parse_argv() p4gf_version_3.log_version_extended(include_checksum=True) log_l10n() if args.enablemismatchedrhs: # Git Fusion should never modify the customer's config file, and # use of this option resulted in the config file losing all of the # comments and formatting the customer had put in place. sys.stderr.write( _('The --enablemismatchedrhs option is deprecated,' ' please use enable-mismatched-rhs config file' ' option instead.\n')) sys.exit(1) repo_name_p4client = None if args.p4client: repo_name_p4client = p4gf_util.argv_to_repo_name(args.p4client) repo_name = _argv_to_repo_name(args.repo_name) p4gf_util.reset_git_enviro() p4 = p4gf_create_p4.create_p4_temp_client() if not p4: raise RuntimeError(_('error connecting to Perforce')) LOG.debug("connected to P4 at %s", p4.port) p4gf_proc.init() try: with ExitStack() as stack: stack.enter_context(p4gf_create_p4.Closer()) p4gf_version_3.version_check() p4gf_branch.init_case_handling(p4) repo_lock = p4gf_lock.RepoLock(p4, repo_name) stack.enter_context(repo_lock) ctx = p4gf_context.create_context(repo_name) ctx.p4gf = p4 ctx.repo_lock = repo_lock initer = InitRepo(p4, repo_lock).set_repo_name(repo_name) initer.context = ctx initer.set_config_file_path(args.config) initer.set_charset(args.charset) initer.set_noclone(args.noclone) initer.set_start(args.start) stack.enter_context(ctx) initer.full_init(repo_name_p4client) except P4.P4Exception as e: _print_stderr(_('Error occurred: {exception}').format(exception=e)) sys.exit(1)
def _global_init(p4): """Check that p4gf_super_init has been run.""" # # The global initialization process below must be idempotent in the sense # that it is safe to perform more than once. As such, there are checks to # determine if work is needed or not, and if that work results in an # error, log and carry on with the rest of the steps, with the assumption # that a previous attempt had failed in the middle (or possibly that # another instance of Git Fusion has started at nearly the same time as # this one). # p4gf_util.has_server_id_or_exit() _ensure_specs_created(p4) _ensure_permission_groups(p4) _ensure_admin_privileges(p4) _ensure_proxy_protects_key(p4)
def main(): """Copy the SSH keys from Perforce to the authorized keys file.""" global LFS_FILE_MAX_SECONDS_TO_KEEP p4gf_util.has_server_id_or_exit() log_l10n() # Set up argument parsing. parser = p4gf_util.create_arg_parser( _("""Removes files from LFS file cache which have not been accessed in some configurable time.""")) group = parser.add_mutually_exclusive_group() group.add_argument( '--hours', nargs=1, help=_('number of hours since last access to keep lfs file')) group.add_argument( '--days', nargs=1, help=_('number of days since last access to keep lfs file')) group.add_argument( '--seconds', nargs=1, help=_('number of seconds since last access to keep lfs file')) parser.add_argument('--gfhome', nargs=1, help=_('set GFHOME')) args = parser.parse_args() if args.gfhome: p4gf_const.P4GF_HOME = args.gfhome[0] try: if args.hours: LFS_FILE_MAX_SECONDS_TO_KEEP = int(args.hours[0]) * 3600 if args.days: LFS_FILE_MAX_SECONDS_TO_KEEP = int(args.days[0]) * 24 * 3600 if args.seconds: LFS_FILE_MAX_SECONDS_TO_KEEP = int(args.seconds[0]) except ValueError: LOG.debug("--hours, --days, --seconds must be integers.") if sys.stdout.isatty(): print("--hours, --days, --seconds must be integers.") sys.exit(1) prune_lfs_file_cache()
def check_readiness(p4): """ Check that P4GF is ready for accepting connections from clients. """ # Note the "clever" use of counter names with a shared prefix that # just happen to be the two counters we are interested in retrieving. # (wanted to avoid another call to p4 counter, but without retrieving # _all_ P4GF counters, which could be millions). fetch_counters = lambda p4: p4.run('counters', '-u', '-e', 'git-fusion-pre*') if p4.connected(): counters = fetch_counters(p4) else: with p4gf_create_p4.p4_connect(p4): counters = fetch_counters(p4) # Check if the "prevent further access" counter has been set, and raise an # error if the counter is anything other than zero. value = fetch_counter_value(counters, p4gf_const.P4GF_COUNTER_PREVENT_NEW_SESSIONS) if value and value != '0': raise RuntimeError( _('Git Fusion is shutting down. Please contact your admin.')) # Check that GF submit trigger is installed and has a compatible version. value = fetch_counter_value(counters, p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION) trigger_version_counter = value.split(":")[0].strip() if value else '0' if int(trigger_version_counter) != int(p4gf_const.P4GF_TRIGGER_VERSION): LOG.error( "Incompatible trigger version: {0} should be {1} but got {2}". format(p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION, p4gf_const.P4GF_TRIGGER_VERSION, trigger_version_counter)) if int(trigger_version_counter) == 0: raise RuntimeError( _('Git Fusion submit triggers are not installed.' ' Please contact your admin.')) else: raise RuntimeError( _('Git Fusion submit triggers need updating.' ' Please contact your admin.')) p4gf_util.has_server_id_or_exit(log=LOG)
def main(): """Parse the command-line arguments and report on locks.""" # pylint: disable=too-many-statements desc = _("Report the currently held locks in Git Fusion.") parser = p4gf_util.create_arg_parser(desc=desc) parser.add_argument('--test', action='store_true', help=_('invoke test mode, acquire locks and report')) parser.add_argument( '--test2', action='store_true', help=_( 'invoke test mode, acquire locks and report, set dead processes.')) args = parser.parse_args() p4gf_util.has_server_id_or_exit() server_id = p4gf_util.get_server_id() p4 = p4gf_create_p4.create_p4_temp_client() if not p4: sys.exit(1) print("Connecting to P4PORT={} as P4USER={}".format(p4.port, p4.user)) if args.test or args.test2: repo_name = "p4gf_test_status_repo" status_key_name = p4gf_p4key.calc_repo_status_p4key_name( repo_name, None) p4gf_p4key.set(p4, status_key_name, 'Push 1 completed successfully') pushid_key_name = p4gf_p4key.calc_repo_push_id_p4key_name(repo_name) p4gf_p4key.set(p4, pushid_key_name, '1') # create a process and kill it and set its dead pid as a RepoLock owner below. if args.test: # A test with nothing stale with ExitStack() as stack: stack.enter_context(p4gf_lock.ReviewsLock(p4)) stack.enter_context(p4gf_lock.RepoLock(p4, repo_name)) stack.enter_context(p4gf_git_repo_lock.read_lock(repo_name)) stack.enter_context( p4gf_git_repo_lock.write_lock(repo_name, upgrade=True)) print_lock_status(p4, server_id) else: # if args.test2 # Now a test with some DEAD processes and a stale view Lock dead_process = subprocess.Popen(['echo', 'x'], stdout=subprocess.DEVNULL) dead_process.kill() while dead_process.returncode is None: dead_process.communicate() lock2 = None with ExitStack() as stack: stack.enter_context(p4gf_lock.ReviewsLock(p4)) # first lock owner lock1 = p4gf_lock.RepoLock(p4, repo_name) # second lock owner with same group_id and a dead pid lock2 = p4gf_lock.RepoLock(p4, repo_name, group_id=lock1.group_id) lock2.process_id = dead_process.pid # acquire the first RepoLock stack.enter_context(lock1) # Use low level method to add this DEAD pid to the group's lock owners lock2.do_acquire() stack.enter_context(p4gf_git_repo_lock.read_lock(repo_name)) stack.enter_context( p4gf_git_repo_lock.write_lock(repo_name, upgrade=True)) print("Test 1:") print_lock_status(p4, server_id) p4gf_p4key.set(p4, pushid_key_name, '2') p4gf_p4key.set(p4, status_key_name, 'Push 2 failed: some error') # Finally lets set the P4GF_P4KEY_LOCK_VIEW - the least likley to be stale p4gf_p4key.set(p4, lock2.lock_key, '1') print("Test 2:") print_lock_status(p4, server_id) # Cant exit the ExistStack unless we clean this p4gf_p4key.delete(p4, lock2.lock_key) # Clean up this lock so the test may be run again p4gf_p4key.delete(p4, lock2.owners_key) # remove test keys p4gf_p4key.delete(p4, status_key_name) p4gf_p4key.delete(p4, pushid_key_name) else: print_lock_status(p4, server_id)
def main(): """set up repo for a view""" p4gf_util.has_server_id_or_exit() args = _parse_argv() p4gf_version.log_version() log_l10n() # !!! view_name_git the untranslated repo name # !!! view_name the translated repo name view_name_p4client = None if args.p4client: view_name_p4client = p4gf_util.argv_to_view_name(args.p4client) view_name_git = p4gf_util.argv_to_view_name(args.view) #strip leading '/' to conform with p4gf_auth_server behavior if view_name_git[0] == '/': view_name_git = view_name_git[1:] view_name = p4gf_translate.TranslateReponame.git_to_repo(view_name_git) p4gf_gitmirror.setup_spawn(view_name) p4gf_util.reset_git_enviro() p4 = p4gf_create_p4.create_p4() if not p4: return INIT_REPO_NOVIEW LOG.debug("connected to P4 at %s", p4.port) p4gf_proc.init() try: with p4gf_create_p4.Closer(): p4gf_version.version_check() with p4gf_lock.view_lock(p4, view_name) as view_lock: # Ensure we have a sane environment. p4gf_init.init(p4) # Now that we can trust that the git-fusion--p4 client exists, # switch to that. Change takes effect immediately, don't need to # re-run p4.connect(). p4.client = p4gf_util.get_object_client_name() # If local config file specified, validate it and store in # Perforce now. Even if client exists (aka repo was already # inited), this is one way for an admin to modify an existing # repo's config. if args.config: if not os.path.exists(args.config): _print_stderr(_("error: missing config file '{}'").format(args.config)) return INIT_REPO_CONFIG_FILE_MISSING with Validator.from_local_file(view_name, p4, args.config) as validator: if not validator.is_valid(args.enablemismatchedrhs): return INIT_REPO_CONFIG_FILE_BAD p4gf_config.create_file_repo_with_contents(p4, view_name, args.config) elif args.charset and not Validator.valid_charset(args.charset): _print_stderr(_("error: invalid charset: {}").format(args.charset)) return INIT_REPO_BAD_CHARSET # Initialize the repository if necessary. print(_("Initializing '{}'...").format(view_name)) r = init_repo(p4, view_name, view_lock, args.charset, args.enablemismatchedrhs, view_name_p4client) if r > INIT_REPO_OK: return r print(_("Initialization complete.")) # Write --enablemismatchedrhs to config file if args.enablemismatchedrhs: config = p4gf_config.read_repo(p4, view_name) config[p4gf_config.SECTION_REPO]\ [p4gf_config.KEY_ENABLE_MISMATCHED_RHS] = str(True) p4gf_config.write_repo_if(p4, p4.fetch_client(), view_name, config) # Populate the repo from Perforce unless --noclone. if not args.noclone: return populate_repo(view_name, view_lock, args.start) except P4.P4Exception as e: _print_stderr(_('Error occurred: {}').format(e)) return INIT_REPO_EXISTS
def main(): """ Process command line arguments and call functions to do the real work of cleaning up the Git mirror and Perforce workspaces. """ log_l10n() p4gf_util.has_server_id_or_exit() # pylint:disable=C0301 # Line too long? Too bad. Keep tabular code tabular. # Set up argument parsing. parser = p4gf_util.create_arg_parser( _('Deletes Git Fusion repositories and workspaces.')) parser.add_argument('-a', '--all', action='store_true', help=_('remove all known Git mirrors')) parser.add_argument('-y', '--delete', action='store_true', help=_('perform the deletion')) parser.add_argument('-v', '--verbose', action='store_true', help=_('print details of deletion process')) parser.add_argument( '-N', '--no-obliterate', action='store_true', help=_('with the --all option, do not obliterate object cache')) parser.add_argument(NTR('views'), metavar=NTR('view'), nargs='*', help=_('name of view to be deleted')) args = parser.parse_args() # pylint:enable=C0301 # Check that either --all, or 'views' was specified. if not args.all and len(args.views) == 0: sys.stderr.write(_('Missing view names; try adding --all option.\n')) sys.exit(2) # Check that --no-obliterate occurs only with --all if not args.all and args.no_obliterate: sys.stderr.write( _('--no-obliterate permitted only with the --all option.\n')) sys.exit(2) with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4( client=p4gf_util.get_object_client_name()) if not p4: return 2 # Sanity check the connection (e.g. user logged in?) before proceeding. try: p4.fetch_client() except P4.P4Exception as e: sys.stderr.write(_('P4 exception occurred: {}').format(e)) sys.exit(1) metrics = DeletionMetrics() if args.all: try: delete_all(args, p4, metrics) except P4.P4Exception as e: sys.stderr.write("{}\n".format(e)) sys.exit(1) else: # Delete the client(s) for the named view(s). for git_view in args.views: view_name = p4gf_translate.TranslateReponame.git_to_repo( git_view) client_name = p4gf_util.view_to_client_name(view_name) try: with p4gf_lock.view_lock(p4, view_name, -1): delete_client(args, p4, client_name, metrics) except P4.P4Exception as e: sys.stderr.write("{}\n".format(e)) if not args.delete: print(_('This was report mode. Use -y to make changes.')) else: print( _('Deleted {:d} files, {:d} groups, {:d} clients, and {:d} counters.' ).format(metrics.files, metrics.groups, metrics.clients, metrics.counters)) if args.all: print(_('Successfully deleted all repos\n')) else: print( _('Successfully deleted repos:\n{}').format("\n".join( args.views)))
def main(): """Process command line arguments and call functions to do the real work of cleaning up the Git mirror and Perforce workspaces. """ # pylint:disable=too-many-branches, too-many-statements log_l10n() # Set up argument parsing. desc = _("""Deletes Git Fusion repositories and workspaces. When you include the -a or --all option, Git Fusion finds and deletes the following for all repos on the current server disregarding specified views: 1) All git-fusion-view clients. 2) Client git-fusion--p4 workspace files. 3) Objects in //.git-fusion/objects/... """) epilog = _("""It is recommended to run 'p4gf_delete_repo.py' without the '-y' flag to preview changes that will be made to the depot before using the '-y' flag for permanent removal. Use -a or --all to permanently delete all repo data for all repos on the Perforce server; be aware that this may take some time, depending on the number and size of the objects. Use -N, --no-obliterate to quickly delete most of the repo's data and continue working. This minimizes the impact to server performance. """) parser = p4gf_util.create_arg_parser(desc, epilog=epilog) parser.add_argument( '-a', '--all', action='store_true', help=_('remove all known Git mirrors on the current server')) parser.add_argument('-y', '--delete', action='store_true', help=_('perform the deletion')) parser.add_argument('-v', '--verbose', action='store_true', help=_('print details of deletion process')) parser.add_argument( '-N', '--no-obliterate', action='store_true', help=_('with the --all option, do not obliterate object cache')) parser.add_argument(NTR('views'), metavar=NTR('view'), nargs='*', help=_('name of view to be deleted')) args = parser.parse_args() p4gf_util.has_server_id_or_exit() # Check that either --all, or 'views' was specified. if not args.all and len(args.views) == 0: sys.stderr.write(_('Missing view names; try adding --all option.\n')) sys.exit(2) if args.all and len(args.views) > 0: sys.stderr.write( _('Ambiguous arguments. Choose --all or a view name.\n')) sys.exit(2) # Check that --no-obliterate occurs only with --all if not args.all and args.no_obliterate: sys.stderr.write( _('--no-obliterate permitted only with the --all option.\n')) sys.exit(2) with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4_temp_client() if not p4: return 2 # Sanity check the connection (e.g. user logged in?) before proceeding. p4gf_branch.init_case_handling(p4) try: p4.fetch_client() except P4.P4Exception as e: sys.stderr.write( _('P4 exception occurred: {exception}').format(exception=e)) sys.exit(1) metrics = DeletionMetrics() if args.all: try: if p4gf_const.READ_ONLY: delete_all_local(args, p4, metrics) else: delete_all(args, p4, metrics) except (p4gf_lock.LockBusy, P4.P4Exception) as e: sys.stderr.write("{exception}\n".format(exception=e)) sys.exit(1) else: # Delete the client(s) for the named view(s). for git_view in args.views: repo_name = p4gf_translate.TranslateReponame.git_to_repo( git_view) client_name = p4gf_util.repo_to_client_name(repo_name) try: if p4gf_const.READ_ONLY: delete_client_local(args, p4, client_name, metrics) else: with p4gf_lock.RepoLock(p4, repo_name, blocking=False): delete_client(args, p4, client_name, metrics) except (p4gf_lock.LockBusy, P4.P4Exception) as e: sys.stderr.write("{exception}\n".format(exception=e)) sys.exit(1) if not args.delete: print(_('This was report mode. Use -y to make changes.')) else: print( _('Deleted {num_files:d} files, {num_groups:d} groups, ' '{num_clients:d} clients, and {num_keys:d} p4keys.').format( num_files=metrics.files, num_groups=metrics.groups, num_clients=metrics.clients, num_keys=metrics.p4keys)) if args.all: print(_('Successfully deleted all repos\n')) else: print( _('Successfully deleted repos:\n{repos}').format( repos="\n".join(args.views)))
def main(): """set up repo for a view""" p4gf_util.has_server_id_or_exit() args = _parse_argv() p4gf_version.log_version() log_l10n() # !!! view_name_git the untranslated repo name # !!! view_name the translated repo name view_name_p4client = None if args.p4client: view_name_p4client = p4gf_util.argv_to_view_name(args.p4client) view_name_git = p4gf_util.argv_to_view_name(args.view) #strip leading '/' to conform with p4gf_auth_server behavior if view_name_git[0] == '/': view_name_git = view_name_git[1:] view_name = p4gf_translate.TranslateReponame.git_to_repo(view_name_git) p4gf_gitmirror.setup_spawn(view_name) p4gf_util.reset_git_enviro() p4 = p4gf_create_p4.create_p4() if not p4: return INIT_REPO_NOVIEW LOG.debug("connected to P4 at %s", p4.port) p4gf_proc.init() try: with p4gf_create_p4.Closer(): p4gf_version.version_check() with p4gf_lock.view_lock(p4, view_name) as view_lock: # Ensure we have a sane environment. p4gf_init.init(p4) # Now that we can trust that the git-fusion--p4 client exists, # switch to that. Change takes effect immediately, don't need to # re-run p4.connect(). p4.client = p4gf_util.get_object_client_name() # If local config file specified, validate it and store in # Perforce now. Even if client exists (aka repo was already # inited), this is one way for an admin to modify an existing # repo's config. if args.config: if not os.path.exists(args.config): _print_stderr( _("error: missing config file '{}'").format( args.config)) return INIT_REPO_CONFIG_FILE_MISSING with Validator.from_local_file(view_name, p4, args.config) as validator: if not validator.is_valid(args.enablemismatchedrhs): return INIT_REPO_CONFIG_FILE_BAD p4gf_config.create_file_repo_with_contents( p4, view_name, args.config) elif args.charset and not Validator.valid_charset( args.charset): _print_stderr( _("error: invalid charset: {}").format(args.charset)) return INIT_REPO_BAD_CHARSET # Initialize the repository if necessary. print(_("Initializing '{}'...").format(view_name)) r = init_repo(p4, view_name, view_lock, args.charset, args.enablemismatchedrhs, view_name_p4client) if r > INIT_REPO_OK: return r print(_("Initialization complete.")) # Write --enablemismatchedrhs to config file if args.enablemismatchedrhs: config = p4gf_config.read_repo(p4, view_name) config[p4gf_config.SECTION_REPO]\ [p4gf_config.KEY_ENABLE_MISMATCHED_RHS] = str(True) p4gf_config.write_repo_if(p4, p4.fetch_client(), view_name, config) # Populate the repo from Perforce unless --noclone. if not args.noclone: return populate_repo(view_name, view_lock, args.start) except P4.P4Exception as e: _print_stderr(_('Error occurred: {}').format(e)) return INIT_REPO_EXISTS
def _global_init(p4): """Check that p4gf_super_init has been run and created the following * user git-fusion-user * depot //P4GF_DEPOT * group git-fusion-pull * group git-fusion-push * protects entries """ # # The global initialization process below must be idempotent in the sense # that it is safe to perform more than once. As such, there are checks to # determine if work is needed or not, and if that work results in an # error, log and carry on with the rest of the steps, with the assumption # that a previous attempt had failed in the middle (or possibly that # another instance of Git Fusion has started at nearly the same time as # this one). # p4gf_util.has_server_id_or_exit() spec_list = { 'user1': p4gf_const.P4GF_USER, 'user2': p4gf_util.gf_reviews_user_name(), 'user3': p4gf_const.P4GF_REVIEWS__NON_GF, 'group': p4gf_const.P4GF_GROUP, 'depot': p4gf_const.P4GF_DEPOT } for spec_type, spec_id in spec_list.items(): spec_type = re.sub(NTR(r'\d$'), '', spec_type) if not p4gf_util.spec_exists(p4, spec_type, spec_id): # pylint:disable=C0301 raise RuntimeError(_("error: {spec_type} '{spec_id}' does not exist." " Please contact your administrator.") .format(spec_type=spec_type, spec_id=spec_id)) # pylint:enable=C0301 for group in [p4gf_group.PERM_PULL, p4gf_group.PERM_PUSH]: c = p4gf_group.create_global_perm(p4, group) if c: _info(_("Global permission group '{}' created.").format(group)) else: _info(_("Global permission group '{}' already exists.").format(group)) c = p4gf_group.create_default_perm(p4) if c: _info(_("Default permission counter '{}' set to '{}'.") .format( p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT , p4gf_group.DEFAULT_PERM )) else: _info(_("Default permission counter '{}' already exists.") .format(p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT)) # Require that single git-fusion-user have admin privileges # over the //P4GF_DEPOT/ depot is_protects_empty = False try: p4.run('protects', '-u', p4gf_const.P4GF_USER, '-m', '//{depot}/...'.format(depot=p4gf_const.P4GF_DEPOT)) except P4.P4Exception: # Why MsgDm_ReferClient here? Because p4d 11.1 returns # "must refer to client" instead of # "Protections table is empty" when given a depot path to # 'p4 protects -m -u'. Surprise! if p4gf_p4msg.find_all_msgid(p4, [ p4gf_p4msgid.MsgDm_ProtectsEmpty , p4gf_p4msgid.MsgDm_ReferClient ]): is_protects_empty = True # All other errors are fatal, propagated. if is_protects_empty: # - order the lines in increasing permission # - end with at least one user (even a not-yet-created user) with super # write user * * //... # admin user git-fusion-user * //... # super user super * //... p4gf_util.set_spec(p4, 'protect', values={ 'Protections': ["super user * * //...", "super user {user} * //...".format(user=p4gf_const.P4GF_USER), "admin user {user} * //{depot}/..." .format(user=p4gf_const.P4GF_USER, depot=p4gf_const.P4GF_DEPOT)]}) _info(_('Protects table set.'))
def main(): """Copy the SSH keys from Perforce to the authorized keys file.""" p4gf_util.has_server_id_or_exit() log_l10n() # Set up argument parsing. parser = p4gf_util.create_arg_parser( _("""Copies SSH public keys from Perforce depot to current user's directory. This script assumes OpenSSH is the SSH implementation in use, and as such, writes to 'authorized_keys' in the ~/.ssh directory. If --ssh2 is used, then writes to 'authorization' in the ~/.ssh2 directory, writing the SSH2 formatted public keys in the 'keys' directory under ~/.ssh2, using the Perforce user names to avoid name collisions. If public keys read from the depot are the wrong format (OpenSSH vs. SSH2), they will be converted when written to disk. """)) parser.add_argument('-r', '--rebuild', action=NTR('store_true'), help=_('rebuild keys file')) parser.add_argument('-v', '--verbose', action=NTR('store_true'), help=_('print details of update process')) parser.add_argument('-2', '--ssh2', action=NTR('store_true'), help=_("produce 'SSH2' output")) parser.add_argument('-f', '--file', help=_('path to authorized keys file')) args = parser.parse_args() # Since this script is called often (by cron), try to reduce the lines # that appear in the log by raising the log level for the p4gf_create_p4 # module. logging.getLogger('p4gf_create_p4').setLevel('WARN') with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4_temp_client() if not p4: return 2 # Sanity check the connection (e.g. user logged in?) before proceeding. try: p4.fetch_client() except P4Exception as e: _print_warn(_('P4 exception occurred: {error}').format(error=e), error=True) sys.exit(1) # Update global settings based on command line arguments. global Verbose Verbose = args.verbose global Ssh2 Ssh2 = args.ssh2 global SshKeysFile SshKeysFile = args.file if not SshKeysFile: SshKeysFile = NTR('~/.ssh2/authorization') if Ssh2 else NTR( '~/.ssh/authorized_keys') if SshKeysFile[0] == '~': SshKeysFile = os.path.expanduser(SshKeysFile) global SshDirectory SshDirectory = os.path.dirname(SshKeysFile) # Update the keys file based either on latest changes or existing files. try: if args.rebuild: rebuild_all_keys(p4) else: update_by_changes(p4) except P4Exception as e: _print_warn(_('P4 exception occurred: {error}').format(error=e), error=True)
def main(): """ Process command line arguments and call functions to do the real work of cleaning up the Git mirror and Perforce workspaces. """ log_l10n() p4gf_util.has_server_id_or_exit() # pylint:disable=C0301 # Line too long? Too bad. Keep tabular code tabular. # Set up argument parsing. parser = p4gf_util.create_arg_parser( _('Deletes Git Fusion repositories and workspaces.')) parser.add_argument('-a', '--all', action='store_true', help=_('remove all known Git mirrors')) parser.add_argument('-y', '--delete', action='store_true', help=_('perform the deletion')) parser.add_argument('-v', '--verbose', action='store_true', help=_('print details of deletion process')) parser.add_argument('-N', '--no-obliterate', action='store_true', help=_('with the --all option, do not obliterate object cache')) parser.add_argument(NTR('views'), metavar=NTR('view'), nargs='*', help=_('name of view to be deleted')) args = parser.parse_args() # pylint:enable=C0301 # Check that either --all, or 'views' was specified. if not args.all and len(args.views) == 0: sys.stderr.write(_('Missing view names; try adding --all option.\n')) sys.exit(2) # Check that --no-obliterate occurs only with --all if not args.all and args.no_obliterate: sys.stderr.write(_('--no-obliterate permitted only with the --all option.\n')) sys.exit(2) with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4(client=p4gf_util.get_object_client_name()) if not p4: return 2 # Sanity check the connection (e.g. user logged in?) before proceeding. try: p4.fetch_client() except P4.P4Exception as e: sys.stderr.write(_('P4 exception occurred: {}').format(e)) sys.exit(1) metrics = DeletionMetrics() if args.all: try: delete_all(args, p4, metrics) except P4.P4Exception as e: sys.stderr.write("{}\n".format(e)) sys.exit(1) else: # Delete the client(s) for the named view(s). for git_view in args.views: view_name = p4gf_translate.TranslateReponame.git_to_repo(git_view) client_name = p4gf_util.view_to_client_name(view_name) try: with p4gf_lock.view_lock(p4, view_name, -1): delete_client(args, p4, client_name, metrics) except P4.P4Exception as e: sys.stderr.write("{}\n".format(e)) if not args.delete: print(_('This was report mode. Use -y to make changes.')) else: print(_('Deleted {:d} files, {:d} groups, {:d} clients, and {:d} counters.').format( metrics.files, metrics.groups, metrics.clients, metrics.counters)) if args.all: print(_('Successfully deleted all repos\n')) else: print(_('Successfully deleted repos:\n{}').format("\n".join(args.views)))
def _global_init(p4): """Check that p4gf_super_init has been run and created the following * user git-fusion-user * depot //P4GF_DEPOT * group git-fusion-pull * group git-fusion-push * protects entries """ # # The global initialization process below must be idempotent in the sense # that it is safe to perform more than once. As such, there are checks to # determine if work is needed or not, and if that work results in an # error, log and carry on with the rest of the steps, with the assumption # that a previous attempt had failed in the middle (or possibly that # another instance of Git Fusion has started at nearly the same time as # this one). # p4gf_util.has_server_id_or_exit() spec_list = { 'user1': p4gf_const.P4GF_USER, 'user2': p4gf_util.gf_reviews_user_name(), 'user3': p4gf_const.P4GF_REVIEWS__NON_GF, 'group': p4gf_const.P4GF_GROUP, 'depot': p4gf_const.P4GF_DEPOT } for spec_type, spec_id in spec_list.items(): spec_type = re.sub(NTR(r'\d$'), '', spec_type) if not p4gf_util.spec_exists(p4, spec_type, spec_id): # pylint:disable=C0301 raise RuntimeError( _("error: {spec_type} '{spec_id}' does not exist." " Please contact your administrator.").format( spec_type=spec_type, spec_id=spec_id)) # pylint:enable=C0301 for group in [p4gf_group.PERM_PULL, p4gf_group.PERM_PUSH]: c = p4gf_group.create_global_perm(p4, group) if c: _info(_("Global permission group '{}' created.").format(group)) else: _info( _("Global permission group '{}' already exists.").format( group)) c = p4gf_group.create_default_perm(p4) if c: _info( _("Default permission counter '{}' set to '{}'.").format( p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT, p4gf_group.DEFAULT_PERM)) else: _info( _("Default permission counter '{}' already exists.").format( p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT)) # Require that single git-fusion-user have admin privileges # over the //P4GF_DEPOT/ depot is_protects_empty = False try: p4.run('protects', '-u', p4gf_const.P4GF_USER, '-m', '//{depot}/...'.format(depot=p4gf_const.P4GF_DEPOT)) except P4.P4Exception: # Why MsgDm_ReferClient here? Because p4d 11.1 returns # "must refer to client" instead of # "Protections table is empty" when given a depot path to # 'p4 protects -m -u'. Surprise! if p4gf_p4msg.find_all_msgid( p4, [p4gf_p4msgid.MsgDm_ProtectsEmpty, p4gf_p4msgid.MsgDm_ReferClient ]): is_protects_empty = True # All other errors are fatal, propagated. if is_protects_empty: # - order the lines in increasing permission # - end with at least one user (even a not-yet-created user) with super # write user * * //... # admin user git-fusion-user * //... # super user super * //... p4gf_util.set_spec(p4, 'protect', values={ 'Protections': [ "super user * * //...", "super user {user} * //...".format( user=p4gf_const.P4GF_USER), "admin user {user} * //{depot}/...".format( user=p4gf_const.P4GF_USER, depot=p4gf_const.P4GF_DEPOT) ] }) _info(_('Protects table set.'))