예제 #1
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
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)
예제 #7
0
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()
예제 #9
0
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)
예제 #11
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
예제 #12
0
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)))
예제 #14
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
예제 #15
0
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.'))
예제 #16
0
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)
예제 #17
0
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)))
예제 #18
0
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.'))