def main(): """Parse command line arguments and decide what should be done.""" desc = _("""p4gf_lfs_http_server.py handles LFS requests over HTTP. Typically it is run via a web server and protected by some form of user authentication. The environment variable REMOTE_USER must be set to the name of a valid Perforce user, which is taken to be the user performing a pull or push operation. """) epilog = _("""If the --port argument is given then a simple HTTP server will be started, listening on the specified port. In lieu of REMOTE_USER, the user name is extracted from the URI, which starts with "/~", followed by the user name. To stop the server, send a terminating signal to the process. """) log_l10n() parser = p4gf_util.create_arg_parser(desc, epilog=epilog) parser.add_argument('-p', '--port', type=int, help=_('port on which to listen for LFS reqeuests')) args = parser.parse_args() if args.port: LOG.info("Listening for LFS-HTTP requests on port %s, pid=%s", args.port, os.getpid()) httpd = wsgiref.simple_server.make_server('', args.port, app_wrapper) print(_('Serving on port {port}...').format(port=args.port)) p4gf_http_common.wsgi_install_signal_handler(httpd) p4gf_proc.install_stack_dumper() httpd.serve_forever() else: # Assume we are running inside a web server... p4gf_proc.install_stack_dumper() _handle_cgi()
def main(): """create Perforce user and client for Git Fusion""" p4gf_version.log_version() try: log_l10n() p4gf_version.version_check() # pylint: disable=W0703 # Catching too general exception except Exception as e: sys.stderr.write(e.args[0] + '\n') sys.exit(1) with p4gf_create_p4.Closer(): p4 = p4gf_create_p4.create_p4() 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() init(p4) return 0
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(): """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(): """ Parse command line arguments and decide what should be done. """ desc = _("""p4gf_http_server.py handles http(s) requests. Typically it is run via a web server and protected by some form of user authentication. The environment variable REMOTE_USER must be set to the name of a valid Perforce user, which is taken to be the user performing a pull or push operation. """) epilog = _("""If the --user argument is given then a simple HTTP server will be started, listening on the port specified by --port. The REMOTE_USER value will be set to the value given to the --user argument. To stop the server, send a terminating signal to the process. """) log_l10n() parser = p4gf_util.create_arg_parser(desc, epilog=epilog) parser.add_argument('-u', '--user', help=_('value for REMOTE_USER variable')) parser.add_argument('-p', '--port', type=int, default=8000, help=_('port on which to listen (default 8000)')) args = parser.parse_args() if args.user: LOG.debug( "Listening for HTTP requests on port {} as user {}, pid={}".format( args.port, args.user, os.getpid())) wrapper = functools.partial(_app_wrapper, args.user) httpd = wsgiref.simple_server.make_server( '', args.port, wrapper, handler_class=GitFusionRequestHandler) print(_('Serving on port {}...').format(args.port)) def _signal_handler(signum, _frame): """ Ensure the web server is shutdown properly. """ LOG.info("received signal {}, pid={}, exiting".format( signum, os.getpid())) httpd.server_close() sys.exit(0) LOG.debug("installing HTTP server signal handler, pid={}".format( os.getpid())) signal.signal(signal.SIGHUP, _signal_handler) signal.signal(signal.SIGINT, _signal_handler) signal.signal(signal.SIGQUIT, _signal_handler) signal.signal(signal.SIGTERM, _signal_handler) signal.signal(signal.SIGTSTP, _signal_handler) p4gf_proc.install_stack_dumper() httpd.serve_forever() else: # Assume we are running inside a web server... _handle_cgi()
def run_main(): """Some initial logging, then run main().""" # Ensure any errors occurring in the setup are sent to stderr, while the # code below directs them to stderr once rather than twice. try: with p4gf_log.ExceptionLogger(squelch=False, write_to_stderr_=True): p4gf_version_3.log_version_extended() log_l10n() p4gf_version_3.version_check() except: # pylint: disable=bare-except # Cannot continue if above code failed. sys.exit(1) # main() already writes errors to stderr, so don't let logger do it again p4gf_log.run_with_exception_logger(main_ignores, write_to_stderr=False)
def main(): """ Parse command line arguments and decide what should be done. """ desc = _("""p4gf_http_server.py handles http(s) requests. Typically it is run via a web server and protected by some form of user authentication. The environment variable REMOTE_USER must be set to the name of a valid Perforce user, which is taken to be the user performing a pull or push operation. """) epilog = _("""If the --user argument is given then a simple HTTP server will be started, listening on the port specified by --port. The REMOTE_USER value will be set to the value given to the --user argument. To stop the server, send a terminating signal to the process. """) log_l10n() parser = p4gf_util.create_arg_parser(desc, epilog=epilog) parser.add_argument('-u', '--user', help=_('value for REMOTE_USER variable')) parser.add_argument('-p', '--port', type=int, default=8000, help=_('port on which to listen (default 8000)')) args = parser.parse_args() if args.user: LOG.debug("Listening for HTTP requests on port {} as user {}, pid={}".format( args.port, args.user, os.getpid())) wrapper = functools.partial(_app_wrapper, args.user) httpd = wsgiref.simple_server.make_server('', args.port, wrapper, handler_class=GitFusionRequestHandler) print(_('Serving on port {}...').format(args.port)) def _signal_handler(signum, _frame): """ Ensure the web server is shutdown properly. """ LOG.info("received signal {}, pid={}, exiting".format(signum, os.getpid())) httpd.server_close() sys.exit(0) LOG.debug("installing HTTP server signal handler, pid={}".format(os.getpid())) signal.signal(signal.SIGHUP, _signal_handler) signal.signal(signal.SIGINT, _signal_handler) signal.signal(signal.SIGQUIT, _signal_handler) signal.signal(signal.SIGTERM, _signal_handler) signal.signal(signal.SIGTSTP, _signal_handler) p4gf_proc.install_stack_dumper() httpd.serve_forever() else: # Assume we are running inside a web server... _handle_cgi()
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 main(): ''' Parse command line arguments and do the work of mirroring Git objects. ''' LOG.debug("main: {}, pid={}".format(p4gf_log.memory_usage(), os.getpid())) log_l10n() if 3 != len(sys.argv): sys.stderr.write(_('usage: p4gf_gitmirror_worker.py <repo> <work-queue-file>')) return 1 view_name = sys.argv[1] path = sys.argv[2] LOG.debug("reading commits from {}".format(path)) p4gf_proc.init() __do_trees(view_name, path) p4gf_proc.stop() LOG.debug("worker done for {}".format(view_name)) return 0
def main(): ''' Parse command line arguments and do the work of mirroring Git objects. ''' LOG.debug("main: {}, pid={}".format(p4gf_log.memory_usage(), os.getpid())) log_l10n() if 3 != len(sys.argv): sys.stderr.write( _('usage: p4gf_gitmirror_worker.py <repo> <work-queue-file>')) return 1 view_name = sys.argv[1] path = sys.argv[2] LOG.debug("reading commits from {}".format(path)) p4gf_proc.init() __do_trees(view_name, path) p4gf_proc.stop() LOG.debug("worker done for {}".format(view_name)) return 0
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 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(): """Copy incoming Git commits to Perforce changelists.""" _log_environ(os.environ) log_l10n() LOG.debug("main() running, pid={}".format(os.getpid())) p4gf_proc.install_stack_dumper() for h in ['-?', '-h', '--help']: if h in sys.argv: print(_('Git Fusion pre-receive hook.')) return 2 with p4gf_create_p4.Closer(): p4gf_version.print_and_exit_if_argv() p4 = p4gf_create_p4.create_p4() if not p4: return 2 p4gf_util.reset_git_enviro(p4) view_name = p4gf_util.cwd_to_view_name() view_lock = p4gf_lock.view_lock_heartbeat_only(p4, view_name) with p4gf_context.create_context(view_name, view_lock) as ctx: # this script is called by git while a context and temp clients # are already in use. Don't sabotage that context by deleting # the temp clients from here. ctx.cleanup_client_pool = False # Read each input line (usually only one unless pushing multiple branches) # and convert to a list of "tuples" from which we can assign branches. prl = [] delete_prl = [] while True: line = sys.stdin.readline() if not line: break LOG.debug('main() raw pre-receive-tuple: {}'.format(line)) prt = PreReceiveTuple.from_line(line) if int(prt.new_sha1, 16) == 0: delete_prl.append(prt) else: prl.append(prt) # Initialize the external process launcher early, before allocating lots # of memory, and just after all other conditions have been checked. p4gf_proc.init() # Prepare for possible spawn of GitMirror worker process by forking # now before allocating lots of memory. p4gf_gitmirror.setup_spawn(view_name) # Kick off garbage collection debugging, if enabled. p4gf_gc.init_gc() # Reject attempt to delete any fully populated branch defined in # p4gf_config. Git Fusion never edits p4gf_config, so Git Fusion never # deletes fully populated branches. Edit p4gf_config yourself if you # want to remove a branch from history. for prt in delete_prl: git_branch_name = prt.git_branch_name() if not git_branch_name: continue branch = ctx.git_branch_name_to_branch(git_branch_name) if not branch: LOG.debug('attempt to delete branch {} which does not exist' .format(git_branch_name)) break if not branch.is_lightweight: raise RuntimeError(_('Cannot delete branches defined in' ' Git Fusion repo config file: {}') .format(git_branch_name)) # Swarm review creates new Git merge commits. Must occur before branch # assignment so that the review reference can be moved to the new merge # commit. gsreview_coll = GSReviewCollection.from_prl(ctx, prl) if gsreview_coll: gsreview_coll.pre_copy_to_p4(prl) # Assign branches to each of the received commits for pushed branches - skip deletes. if prl: assigner = Assigner(ctx.branch_dict(), prl, ctx) assigner.assign() # For each of the heads being pushed, copy their commits to Perforce. if prl: try: err = _copy( ctx , prl = prl , assigner = assigner , gsreview_coll = gsreview_coll) # branch push if err: return _clean_exit(err) except RuntimeError as err: # Log the error. The return call below eats the error and stack trace. LOG.exception(NTR("_copy() raised exception.")) return _clean_exit(err) # For each of the heads being deleted, remove the branch definition from p4gf_config2 if delete_prl: p4gf_call_git.prohibit_interrupt(view_name, os.getpid()) try: err = _delete(ctx, delete_prl) # branch delete if err: return _clean_exit(err) except RuntimeError as err: # Log the error. The return call below eats the error and stack trace. LOG.exception(NTR("_delete() raised exception.")) return _clean_exit(err) # Process all of the tags at once. err = p4gf_tag.process_tags(ctx, prl + delete_prl) if err: return _clean_exit(err) # If we have any new Git Swarm review references that # auth/http_server must rename, send a list of such # references across process boundary, via a file. if gsreview_coll: gsreview_coll.to_file() p4gf_gc.process_garbage("at end of pre_receive_hook") p4gf_gc.report_objects(NTR("at end of pre_receive_hook")) return 0
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(): """Do the thing.""" try: log_l10n() parse_argv() global P4PORT, P4USER needs_exit = False if not P4PORT and "P4PORT" not in os.environ: Verbosity.report(Verbosity.INFO, 'P4PORT is neither set in the environment nor passed as an option.') needs_exit = True if not P4USER and "P4USER" not in os.environ: Verbosity.report(Verbosity.INFO, 'P4USER is neither set in the environment nor passed as an option.') needs_exit = True # Check that a pre-existing P4GF_ENV config file P4PORT conflicts with the --port option if p4gf_const.P4GF_ENV and not Create_P4GF_CONFIG and P4PORT: if P4PORT != os.environ['P4PORT']: Verbosity.report(Verbosity.INFO, "conflicting P4PORT in args: {0} and P4GF_ENV {1} : P4PORT = {2}. Stopping." .format(P4PORT, p4gf_const.P4GF_ENV, os.environ['P4PORT'])) needs_exit = True else: Verbosity.report(Verbosity.INFO, "P4PORT argument is identically configured in {0}. Proceeding.".format( p4gf_const.P4GF_ENV )) if needs_exit: sys.exit(1) p4gf_version.version_check() # Connect. global p4 if not P4USER: P4USER = os.environ['P4USER'] p4 = p4gf_create_p4.create_p4(port=P4PORT, user=P4USER) if not p4: raise RuntimeError(_("Failed to connect to P4.")) P4PORT = p4.port P4USER = p4.user check_and_create_default_p4gf_env_config() if SHOW_IDS: show_all_server_ids() sys.exit(0) Verbosity.report(Verbosity.INFO, "P4PORT : {}".format(p4.port)) Verbosity.report(Verbosity.INFO, "P4USER : {}".format(p4.user)) _ensure_case_sensitive() # Require that we have super permission. # Might as well keep the result in case we need to write a new protect # table later. Saves a 'p4 protect -o' trip to the server protect_lines = fetch_protect() ensure_server_id() ensure_users() ensure_group() ensure_depot() ensure_protect(protect_lines) ensure_protects_configurable() check_triggers() initialize_all_gf_reviews() # pylint: disable=W0703 # Catching too general exception except Exception as e: sys.stderr.write(str(e) + '\n') p4gf_create_p4.close_all() sys.exit(1)
def do_it(self): """Perform all of the setup, processing, and clean up. :rtype: int :return: status code for the process upon exit. """ p4gf_util.log_environ(LOG, os.environ, self.label) log_l10n() p4gf_proc.install_stack_dumper() # Kick off garbage collection debugging, if enabled. p4gf_mem_gc.init_gc() # Use ExitStack to avoid deeply nested code. with ExitStack() as stack: stack.enter_context(p4gf_create_p4.Closer()) p4 = p4gf_create_p4.create_p4_temp_client() if not p4: return 2 repo_name = p4gf_path.cwd_to_repo_name() p4gf_util.reset_git_enviro() # Initialize the external process launcher early, before # allocating lots of memory, and just after all other # conditions have been checked. p4gf_proc.init() # Assume that something bad will happen (especially with preflight). exit_code = os.EX_SOFTWARE try: p4gf_log.configure_for_repo(repo_name) gid = os.environ[p4gf_const.P4GF_FORK_PUSH] self.before_p4key_lock(repo_name) with p4gf_lock.RepoLock(p4, repo_name, group_id=gid) as repo_lock: # Work to be done with the p4key lock... self.context = p4gf_context.create_context(repo_name) self.context.p4gf = p4 self.context.repo_lock = repo_lock self.context.foruser = os.getenv(p4gf_const.P4GF_FORUSER) stack.enter_context(self.context) self.before() exit_code = self.process() if self.after_requires_write_lock(): # Work to be done without the p4key lock, but with the # write lock. Note that we release the p4key lock # before acquiring the write lock to avoid deadlock # with the foreground process, which always gets the # repo read/write lock _before_ acquiring the p4key # lock. Hence all this complication with the locks. with p4gf_git_repo_lock.write_lock(repo_name): self.after(exit_code) else: # The after() method does not need a write lock... self.after(exit_code) finally: self.cleanup() p4gf_proc.stop() # Random tasks after all of the locks have been released. msg = NTR("at end of {hook}").format(hook=self.label) p4gf_mem_gc.process_garbage(msg) p4gf_mem_gc.report_objects(msg) return exit_code
sys.stderr.write('\n\t'.join(view_list)) sys.stderr.write('\n') sys.exit(2) view_list = args.views for view_name in view_list: sys.argv = [ 'p4gf_auth_server.py', '--user={}'.format(p4gf_const.P4GF_USER), 'git-upload-pack', view_name ] p4gf_auth_server.main(poll_only=True) if __name__ == "__main__": # Ensure any errors occurring in the setup are sent to stderr, while the # code below directs them to stderr once rather than twice. try: # thwart pylint identical code detection with two empty lines below with p4gf_log.ExceptionLogger(squelch=False, write_to_stderr_=True): p4gf_log.record_argv() p4gf_version.log_version() log_l10n() p4gf_version.version_check() # pylint: disable=W0702 except: # Cannot continue if above code failed. exit(1) # main() already writes errors to stderr, so don't let logger do it again p4gf_log.run_with_exception_logger(main, write_to_stderr=False)
def main(): """Do the thing.""" try: log_l10n() parse_argv() global P4PORT, P4USER needs_exit = False if not P4PORT and "P4PORT" not in os.environ: Verbosity.report( Verbosity.INFO, 'P4PORT is neither set in the environment nor passed as an option.' ) needs_exit = True if not P4USER and "P4USER" not in os.environ: Verbosity.report( Verbosity.INFO, 'P4USER is neither set in the environment nor passed as an option.' ) needs_exit = True # Check that a pre-existing P4GF_ENV config file P4PORT conflicts with the --port option if p4gf_const.P4GF_ENV and not Create_P4GF_CONFIG and P4PORT: if P4PORT != os.environ['P4PORT']: Verbosity.report( Verbosity.INFO, "conflicting P4PORT in args: {0} and P4GF_ENV {1} : P4PORT = {2}. Stopping." .format(P4PORT, p4gf_const.P4GF_ENV, os.environ['P4PORT'])) needs_exit = True else: Verbosity.report( Verbosity.INFO, "P4PORT argument is identically configured in {0}. Proceeding." .format(p4gf_const.P4GF_ENV)) if needs_exit: sys.exit(1) p4gf_version.version_check() # Connect. global p4 if not P4USER: P4USER = os.environ['P4USER'] p4 = p4gf_create_p4.create_p4(port=P4PORT, user=P4USER) if not p4: raise RuntimeError(_("Failed to connect to P4.")) P4PORT = p4.port P4USER = p4.user check_and_create_default_p4gf_env_config() if SHOW_IDS: show_all_server_ids() sys.exit(0) Verbosity.report(Verbosity.INFO, "P4PORT : {}".format(p4.port)) Verbosity.report(Verbosity.INFO, "P4USER : {}".format(p4.user)) _ensure_case_sensitive() # Require that we have super permission. # Might as well keep the result in case we need to write a new protect # table later. Saves a 'p4 protect -o' trip to the server protect_lines = fetch_protect() ensure_server_id() ensure_users() ensure_group() ensure_depot() ensure_protect(protect_lines) ensure_protects_configurable() check_triggers() initialize_all_gf_reviews() # pylint: disable=W0703 # Catching too general exception except Exception as e: sys.stderr.write(str(e) + '\n') p4gf_create_p4.close_all() sys.exit(1)
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(): """Do the thing.""" # pylint: disable=too-many-statements, too-many-branches try: log_l10n() parse_argv() global P4PORT, P4USER, P4CLIENT needs_exit = False if not P4PORT and "P4PORT" not in os.environ: Verbosity.report( Verbosity.INFO, _('P4PORT is neither set in the environment nor passed as an option.')) needs_exit = True if not P4USER and "P4USER" not in os.environ: Verbosity.report( Verbosity.INFO, _('P4USER is neither set in the environment nor passed as an option.')) needs_exit = True # Check that a pre-existing P4GF_ENV config file P4PORT conflicts with the --port option if p4gf_const.P4GF_ENV and not Create_P4GF_CONFIG and P4PORT: if P4PORT != os.environ['P4PORT']: Verbosity.report( Verbosity.INFO, _("conflicting P4PORT in args: {p4port} and " "P4GF_ENV {env} : P4PORT = {env_p4port}. Stopping.") .format(p4port=P4PORT, env=p4gf_const.P4GF_ENV, env_p4port=os.environ['P4PORT'])) needs_exit = True else: Verbosity.report( Verbosity.INFO, _("P4PORT argument is identically configured in {0}. Proceeding.") .format(p4gf_const.P4GF_ENV)) if needs_exit: sys.exit(1) p4gf_version_3.version_check() # Connect. global p4 if not P4USER: P4USER = os.environ['P4USER'] # if needed, set a bogus client name so that the default to hostname will not be used. if "P4CLIENT" not in os.environ: P4CLIENT = 'GF-' + str(uuid.uuid4().hex).lower()[-10:] os.environ['P4CLIENT'] = P4CLIENT else: P4CLIENT = os.environ['P4CLIENT'] p4 = p4gf_create_p4.create_p4(port=P4PORT, user=P4USER, client=P4CLIENT) if not p4: raise RuntimeError(_("Failed to connect to P4.")) P4PORT = p4.port P4USER = p4.user check_and_create_default_p4gf_env_config() if SHOW_IDS: show_all_server_ids() sys.exit(0) Verbosity.report(Verbosity.INFO, "P4PORT : {}".format(p4.port)) Verbosity.report(Verbosity.INFO, "P4USER : {}".format(p4.user)) # Require that we have super permission. # Might as well keep the result in case we need to write a new protect # table later. Saves a 'p4 protect -o' trip to the server protect_lines = fetch_protect() if P4_PASSWD and p4_security_level() > 0 and not strong_passwd(P4_PASSWD): Verbosity.report( Verbosity.ERROR, _("This Perforce server requires a strong password: >= 8 characters and")) Verbosity.report( Verbosity.ERROR, _("with mixed case or contain non alphabetic characters.")) sys.exit(1) ensure_server_id() ensure_group() ensure_users() ensure_depot() ensure_protect(protect_lines) ensure_protects_configurable() set_proxy_protects_key() check_triggers() initialize_all_gf_reviews() except Exception as e: # pylint: disable=broad-except sys.stderr.write(str(e) + '\n') p4gf_create_p4.close_all() sys.exit(1)
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(): """Copy incoming Git commits to Perforce changelists.""" _log_environ(os.environ) log_l10n() LOG.debug("main() running, pid={}".format(os.getpid())) p4gf_proc.install_stack_dumper() for h in ['-?', '-h', '--help']: if h in sys.argv: print(_('Git Fusion pre-receive hook.')) return 2 with p4gf_create_p4.Closer(): p4gf_version.print_and_exit_if_argv() p4 = p4gf_create_p4.create_p4() if not p4: return 2 p4gf_util.reset_git_enviro(p4) view_name = p4gf_util.cwd_to_view_name() view_lock = p4gf_lock.view_lock_heartbeat_only(p4, view_name) with p4gf_context.create_context(view_name, view_lock) as ctx: # this script is called by git while a context and temp clients # are already in use. Don't sabotage that context by deleting # the temp clients from here. ctx.cleanup_client_pool = False # Read each input line (usually only one unless pushing multiple branches) # and convert to a list of "tuples" from which we can assign branches. prl = [] delete_prl = [] while True: line = sys.stdin.readline() if not line: break LOG.debug('main() raw pre-receive-tuple: {}'.format(line)) prt = PreReceiveTuple.from_line(line) if int(prt.new_sha1, 16) == 0: delete_prl.append(prt) else: prl.append(prt) # Initialize the external process launcher early, before allocating lots # of memory, and just after all other conditions have been checked. p4gf_proc.init() # Prepare for possible spawn of GitMirror worker process by forking # now before allocating lots of memory. p4gf_gitmirror.setup_spawn(view_name) # Kick off garbage collection debugging, if enabled. p4gf_gc.init_gc() # Reject attempt to delete any fully populated branch defined in # p4gf_config. Git Fusion never edits p4gf_config, so Git Fusion never # deletes fully populated branches. Edit p4gf_config yourself if you # want to remove a branch from history. for prt in delete_prl: git_branch_name = prt.git_branch_name() if not git_branch_name: continue branch = ctx.git_branch_name_to_branch(git_branch_name) if not branch: LOG.debug( 'attempt to delete branch {} which does not exist'. format(git_branch_name)) break if not branch.is_lightweight: raise RuntimeError( _('Cannot delete branches defined in' ' Git Fusion repo config file: {}').format( git_branch_name)) # Swarm review creates new Git merge commits. Must occur before branch # assignment so that the review reference can be moved to the new merge # commit. gsreview_coll = GSReviewCollection.from_prl(ctx, prl) if gsreview_coll: gsreview_coll.pre_copy_to_p4(prl) # Assign branches to each of the received commits for pushed branches - skip deletes. if prl: assigner = Assigner(ctx.branch_dict(), prl, ctx) assigner.assign() # For each of the heads being pushed, copy their commits to Perforce. if prl: try: err = _copy(ctx, prl=prl, assigner=assigner, gsreview_coll=gsreview_coll) # branch push if err: return _clean_exit(err) except RuntimeError as err: # Log the error. The return call below eats the error and stack trace. LOG.exception(NTR("_copy() raised exception.")) return _clean_exit(err) # For each of the heads being deleted, remove the branch definition from p4gf_config2 if delete_prl: p4gf_call_git.prohibit_interrupt(view_name, os.getpid()) try: err = _delete(ctx, delete_prl) # branch delete if err: return _clean_exit(err) except RuntimeError as err: # Log the error. The return call below eats the error and stack trace. LOG.exception(NTR("_delete() raised exception.")) return _clean_exit(err) # Process all of the tags at once. err = p4gf_tag.process_tags(ctx, prl + delete_prl) if err: return _clean_exit(err) # If we have any new Git Swarm review references that # auth/http_server must rename, send a list of such # references across process boundary, via a file. if gsreview_coll: gsreview_coll.to_file() p4gf_gc.process_garbage("at end of pre_receive_hook") p4gf_gc.report_objects(NTR("at end of pre_receive_hook")) return 0
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)))
sys.stderr.write(_('Defined views:\n\t')) sys.stderr.write('\n\t'.join(view_list)) sys.stderr.write('\n') sys.exit(2) view_list = args.views for view_name in view_list: sys.argv = [ 'p4gf_auth_server.py' , '--user={}'.format(p4gf_const.P4GF_USER) , 'git-upload-pack' , view_name] p4gf_auth_server.main(poll_only=True) if __name__ == "__main__": # Ensure any errors occurring in the setup are sent to stderr, while the # code below directs them to stderr once rather than twice. try: # thwart pylint identical code detection with two empty lines below with p4gf_log.ExceptionLogger(squelch=False, write_to_stderr_=True): p4gf_log.record_argv() p4gf_version.log_version() log_l10n() p4gf_version.version_check() # pylint: disable=W0702 except: # Cannot continue if above code failed. exit(1) # main() already writes errors to stderr, so don't let logger do it again p4gf_log.run_with_exception_logger(main, write_to_stderr=False)
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)))