예제 #1
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
def log_info(created, user):
    """Create Perforce user git-fusion-user if not already exists."""
    if created:
        Verbosity.report(Verbosity.INFO, _("User '{}' created.").format(user))
    else:
        Verbosity.report(Verbosity.INFO, _("User '{}' already exists. Not creating.")
                     .format(user))
    return created
예제 #5
0
def _init_if_needed(p4, started_p4key, complete_p4key, func, nop_msg):
    """Call func to do initialization if keys are not set.

    Check that the completed p4key is non-zero, as that indicates that
    initialization has already been done.

    If neither the started nor complete key are set, set the started key,
    call the function, and finally set the complete key.

    If only the started key is set, there may be an initialization attempt in
    progress.  Give it a chance to complete before assuming it has failed and
    restarting the initialization.

    Arguments:
      p4 -- P4 API object
      started_p4key -- name of init started p4key
      complete_p4key -- name of init completed p4key
      func -- initialization function to be called, takes a P4 argument.
              Must be idempotent since it is possible initialization may
              be performed more than once.
      nop_msg -- message to report if no initialization is needed

    Return True if initialization performed, False it not needed.
    """
    if P4Key.is_set(p4, complete_p4key):
        # Short-circuit when there is nothing to be done.
        Verbosity.report(Verbosity.INFO, nop_msg)
        return False

    check_times = 5

    while True:
        # If initialization has not been started, start it now.
        # Check before set to avoid a needless database write,
        # especially since this is run on every pull and push.
        if not P4Key.is_set(p4, started_p4key):
            if P4Key.acquire(p4, started_p4key):
                func(p4)
                # Set a p4key so we will not repeat initialization later.
                P4Key.acquire(p4, complete_p4key)
                return True

        # If initialization has been completed, we're done.
        if P4Key.is_set(p4, complete_p4key):
            Verbosity.report(Verbosity.INFO, nop_msg)
            return False

        # Another process started initialization.  It may still be working on
        # it or it may have died.  Wait a bit to give it a chance to complete.
        time.sleep(1)
        check_times -= 1
        if not check_times:
            # Other process failed to finish perhaps.
            # Steal the "lock" and do the init ourselves.
            P4Key.delete(p4, started_p4key)
        elif check_times < 0:
            raise RuntimeError(_('error: unable to aquire lock for initialization'))
예제 #6
0
def ensure_depot():
    """Create depot P4GF_DEPOT if not already exists."""
    created = p4gf_util.ensure_depot_gf(p4)
    if created:
        Verbosity.report(Verbosity.INFO, _("Depot '{}' created.").format(p4gf_const.P4GF_DEPOT))
    else:
        Verbosity.report(Verbosity.INFO, _("Depot '{}' already exists. Not creating.")
                     .format(p4gf_const.P4GF_DEPOT))
    return created
예제 #7
0
def _parse_argv():
    """Parse command line arguments.

    Only version, help options for now.
    """
    parser = p4gf_util.create_arg_parser(_('Initializes a Git Fusion server.'))
    Verbosity.add_parse_opts(parser)
    args = parser.parse_args()
    Verbosity.parse_level(args)
예제 #8
0
def log_info(created, user):
    """Create Perforce user git-fusion-user if not already exists."""
    if created:
        Verbosity.report(Verbosity.INFO, _("User '{}' created.").format(user))
    else:
        Verbosity.report(
            Verbosity.INFO,
            _("User '{}' already exists. Not creating.").format(user))
    return created
예제 #9
0
def set_proxy_protects_key():
    """Get server's dm.proxy_protects and store as a key for Git Fusion."""
    v = p4gf_util.first_value_for_key(
        p4.run('configure', 'show', CONFIGURABLE_PROXY_PROTECTS),
        KEY_VALUE)
    v = 'false' if v == '0' else 'true'
    P4Key.set(p4, p4gf_const.P4GF_P4KEY_PROXY_PROTECTS, v)
    Verbosity.report(
        Verbosity.INFO, _("Configurable '{configurable}' is set to {value}.")
        .format(configurable=CONFIGURABLE_PROXY_PROTECTS, value=v))
예제 #10
0
def _check_for_old_p4key(p4):
    """Raise an exception if 2013.1 upgrade incomplete.

    If a proper upgrade from 2012.2 to 2013.1+ is not done, an old p4key will
    be present.  Raise an exception if it is.
    """
    old_p4key_pattern = p4gf_const.P4GF_P4KEY_OLD_UPDATE_AUTH_KEYS.format('*')
    if P4Key.get_all(p4, old_p4key_pattern):
        raise RuntimeError(_('error: Git Fusion 2012.2 artifacts detected.'
                             ' Upgrade required for use with 2013.1+.'
                             ' Please contact your administrator.'))
    Verbosity.report(Verbosity.DEBUG, _('Old 2012.2 p4key not present.'))
예제 #11
0
def ensure_depot():
    """Create depot P4GF_DEPOT if not already exists."""
    created = p4gf_util.ensure_depot_gf(p4)
    if created:
        Verbosity.report(
            Verbosity.INFO,
            _("Depot '{}' created.").format(p4gf_const.P4GF_DEPOT))
    else:
        Verbosity.report(
            Verbosity.INFO,
            _("Depot '{}' already exists. Not creating.").format(
                p4gf_const.P4GF_DEPOT))
    return created
예제 #12
0
def fetch_triggers():
    """Return trigger table as a list of lines."""

    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('triggers','-o')
    if p4.errors:
        Verbosity.report(Verbosity.ERROR, _("Unable to run 'p4 triggers -o'."))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)

    triggers = p4gf_util.first_value_for_key(r, KEY_TRIGGERS)
    return triggers
예제 #13
0
def fetch_triggers():
    """Return trigger table as a list of lines."""
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('triggers', '-o')
    if p4.errors:
        Verbosity.report(Verbosity.ERROR, _("Unable to run 'p4 triggers -o'."))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)

    triggers = p4gf_util.first_value_for_key(r, KEY_TRIGGERS)
    LOG.debug('retrieved triggers: %s', triggers)
    return triggers
예제 #14
0
def ensure_protects_configurable():
    """Grant 'p4 protects -u' permission to admin users."""
    v = p4gf_util.first_value_for_key(
            p4.run('configure', 'show', CONFIGURABLE_ALLOW_ADMIN),
            KEY_VALUE)
    if v == '1':
        Verbosity.report(Verbosity.INFO, _("Configurable '{}' already set to 1. Not setting.")
                     .format(CONFIGURABLE_ALLOW_ADMIN))
        return False

    p4.run('configure', 'set', '{}=1'.format(CONFIGURABLE_ALLOW_ADMIN))
    Verbosity.report(Verbosity.INFO, _("Configurable '{}' set to 1.")
                 .format(CONFIGURABLE_ALLOW_ADMIN))
    return True
예제 #15
0
def ensure_group():
    """Create Perforce group git-fusion-group if not already exists."""
    users = []
    # Keep the order of the users in the same order that P4 insists on
    # (if the order doesn't match then the group is updated repeatedly).
    users.append(p4gf_const.P4GF_REVIEWS__ALL_GF)
    users.append(p4gf_const.P4GF_REVIEWS__NON_GF)
    users.append(p4gf_util.gf_reviews_user_name())
    users.append(p4gf_const.P4GF_USER)
    args = [p4, NTR("group")]
    spec = {'Timeout': NTR('unlimited'), 'Users': users}
    kwargs = {'spec_id': p4gf_const.P4GF_GROUP, 'values': spec}
    if not p4gf_util.ensure_spec(*args, **kwargs):
        # We change the list of users in the group from time to time,
        # so ensure the membership is up to date.
        users = p4gf_util.first_dict(p4.run('group', '-o', p4gf_const.P4GF_GROUP))['Users']
        # Add the gf_reviews_user_name if not already in the group.
        # This avoids removing already existing reviews users from multiple GF instances.
        if not p4gf_util.gf_reviews_user_name() in users:
            users.append(p4gf_util.gf_reviews_user_name())
            spec = {'Timeout': NTR('unlimited'), 'Users': users}
            kwargs = {'spec_id': p4gf_const.P4GF_GROUP, 'values': spec}
            if p4gf_util.ensure_spec_values(*args, **kwargs):
                Verbosity.report(Verbosity.INFO
                                , _("Group '{}' updated.").format(p4gf_const.P4GF_GROUP))
            else:
                Verbosity.report(Verbosity.INFO, _("Group '{}' already up to date.")
                                 .format(p4gf_const.P4GF_GROUP))
        else:
            Verbosity.report(Verbosity.INFO, _("Group '{}' already up to date.")
                             .format(p4gf_const.P4GF_GROUP))
        return False
    else:
        Verbosity.report(Verbosity.INFO, _("Group '{}' created.").format(p4gf_const.P4GF_GROUP))
    return True
예제 #16
0
def check_for_localhost(id_from_file, server_id):
    """Validate that server_id is not being set to 'localhost'."""
    needs_exit = False
    if id_from_file == 'localhost' and server_id == 'localhost':
        Verbosity.report(
            Verbosity.INFO,
            _("Your server_id file '{path}' is set to 'localhost'."
              " Use the --id argument to choose another id.").
            format(path=p4gf_util.server_id_file_path()))
        needs_exit = True
    if server_id == 'localhost' and not id_from_file:
        if not ID_FROM_ARGV:
            Verbosity.report(
                Verbosity.INFO,
                _("Git Fusion is attempting to use the default hostname "
                  "'localhost' as the server_id which is not permitted.\n"
                  "Use the --id argument to choose another id."))
            needs_exit = True
        else:
            Verbosity.report(
                Verbosity.INFO,
                _("server_id 'localhost' is not permitted. "
                  " Use the --id argument to choose another id."))
        needs_exit = True
    if server_id == 'localhost' and id_from_file:
        Verbosity.report(
            Verbosity.INFO,
            _("Your server_id file '{path}' is already set to '{server_id}'."
              "\nYou may not override it with 'localhost'."
              " Use the --id argument to choose another id.").
            format(path=p4gf_util.server_id_file_path(), server_id=id_from_file))
        needs_exit = True
    if needs_exit:
        sys.exit(1)
예제 #17
0
def show_all_server_ids():
    '''List current Git Fusion server ids.'''

    server_ids = p4.run('counters', '-u', '-e', p4gf_const.P4GF_COUNTER_SERVER_ID + '*')
    ids = []
    this_server = p4gf_util.read_server_id_from_file()
    for eyed in server_ids:
        if 'counter' in eyed :
            id_ = eyed['counter'].replace(p4gf_const.P4GF_COUNTER_SERVER_ID,'')
            if this_server == id_:
                id_ = "* " + id_
            ids.append(( id_, eyed['value']))

    if ids:
        Verbosity.report(Verbosity.INFO, _("Git Fusion server IDs: {0}").format(ids))
예제 #18
0
def ensure_protects_configurable():
    """Grant 'p4 protects -u' permission to admin users."""
    v = p4gf_util.first_value_for_key(
        p4.run('configure', 'show', CONFIGURABLE_ALLOW_ADMIN),
        KEY_VALUE)
    if v == '1':
        Verbosity.report(
            Verbosity.INFO, _("Configurable '{configurable}' already set to 1. Not setting.")
            .format(configurable=CONFIGURABLE_ALLOW_ADMIN))
        return False

    p4.run('configure', 'set', '{}=1'.format(CONFIGURABLE_ALLOW_ADMIN))
    Verbosity.report(Verbosity.INFO, _("Configurable '{configurable}' set to 1.")
                     .format(configurable=CONFIGURABLE_ALLOW_ADMIN))
    return True
예제 #19
0
def set_passwd_and_login(created, user, passwd=None):
    """If creating the user, conditionally prompt for and set the passwd."""
    global P4_PASSWD, PROMPT_FOR_PASSWD
    if created:
        if PROMPT_FOR_PASSWD:
            prompt_msg = _("Set one password for Perforce users 'git-fusion-user'"
                           "\nand 'git-fusion-reviews-*'.")
            # When creating additional Git Fusion instance only the new reviews will be created.
            # Catch this case and avoid a misleading prompt.
            if user == p4gf_util.gf_reviews_user_name():
                prompt_msg = _("Enter a new password for Perforce user '{user}'.").format(
                    user=user)
            try:
                P4_PASSWD = get_passwd(prompt_msg)
            except KeyboardInterrupt:
                Verbosity.report(
                    Verbosity.INFO,
                    _("\n Stopping. Passwords not set."))
                sys.exit(1)
            # If we prompted, do so once and use for all the service users,
            # even if the user enters no password at all.
            PROMPT_FOR_PASSWD = False
            if not P4_PASSWD:
                Verbosity.report(
                    Verbosity.INFO,
                    _("Empty password. Not setting passwords."))

        # passwd may be suppressed with --nopasswd option, which also suppresses the prompt.
        # We always set the passwd for unknown_git - from random passwd=xxx parameter
        # The global P4_PASSWd for the GF users may not be set (--nopasswd)
        if P4_PASSWD or passwd:
            if passwd:
                set_passwd(user, passwd)
            else:
                set_passwd(user, P4_PASSWD)
            Verbosity.report(
                Verbosity.INFO, _("Password set for Perforce user '{user}'.")
                .format(user=user))
            r = p4.run_login(user)
            msg = re.sub(user, "'" + user + "'", r[0])
            Verbosity.report(Verbosity.INFO, msg)
    else:
        if user in (p4gf_const.P4GF_USER, p4gf_const.P4GF_REVIEWS__NON_GF,
                    p4gf_const.P4GF_REVIEWS__ALL_GF, p4gf_util.gf_reviews_user_name()):
            if p4_has_login(user) == LOGIN_NEEDS_TICKET:
                r = p4.run_login(user)
                msg = re.sub(user, "'" + user + "'", r[0])
                Verbosity.report(Verbosity.INFO, msg)
예제 #20
0
def get_auth_method():
    """Return the configured auth method perforce or ldap."""
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('configure', 'show', 'auth.default.method')
    if p4.errors:
        Verbosity.report(Verbosity.ERROR,
                _("Unable to run 'p4 configure show auth.default.method'."))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)

    auth_method = None
    if len(r):
        auth_method = p4gf_util.first_value_for_key(r, 'Value')
    LOG.debug('auth.default.method = %s', auth_method)
    return auth_method
예제 #21
0
def init(p4):
    """Ensure both global and host-specific initialization are completed.
    """
    started_counter = p4gf_const.P4GF_COUNTER_INIT_STARTED
    complete_counter = p4gf_const.P4GF_COUNTER_INIT_COMPLETE
    if not old_counter_present(p4):
        Verbosity.report(Verbosity.DEBUG, _('Old 2012.2 counter not present.'))
    if not _maybe_perform_init(p4, started_counter, complete_counter,
                               _global_init):
        Verbosity.report(Verbosity.INFO,
                         _('Permissions already initialized. Not changing.'))
    server_id = p4gf_util.get_server_id()
    started_counter = p4gf_const.P4GF_COUNTER_INIT_STARTED + '-' + server_id
    complete_counter = p4gf_const.P4GF_COUNTER_INIT_COMPLETE + '-' + server_id
    p4gf_dir = p4gf_const.P4GF_HOME
    client_name = p4gf_util.get_object_client_name()

    def client_init(p4):
        '''Perform host-specific initialization (and create sample usermap).'''
        # Set up the host-specific client.
        _create_client(p4, client_name, p4gf_dir)
        # Ensure the default user map and global config files are in place.
        _write_user_map(p4, client_name, p4gf_dir)
        p4gf_config.create_file_global(p4)
        _delete_old_init_counters(p4, server_id)

    if not _maybe_perform_init(p4, started_counter, complete_counter,
                               client_init):
        Verbosity.report(
            Verbosity.INFO,
            _('Client and usermap already initialized. Not changing.'))

        # If client already created, make sure it hasn't been tweaked.
        ###: do we really need to handle this case? this is here just to pass the tests
        view = [
            '//{depot}/... //{client}/...'.format(depot=p4gf_const.P4GF_DEPOT,
                                                  client=client_name)
        ]
        p4gf_util.ensure_spec_values(p4, 'client', client_name, {
            'Root': p4gf_dir,
            'View': view
        })

    # Perform any necessary upgrades within a "lock" to avoid race conditions.
    # For now, the lock is global, but could conceivably loosen to host-only.
    started_counter = p4gf_const.P4GF_COUNTER_UPGRADE_STARTED
    complete_counter = p4gf_const.P4GF_COUNTER_UPGRADE_COMPLETE
    if not _maybe_perform_init(p4, started_counter, complete_counter,
                               _upgrade_p4gf):
        Verbosity.report(
            Verbosity.INFO,
            _('Global config file already initialized. Not changing.'))

    # Require non-empty Git config user.name and user.email.
    _ensure_git_config_non_empty('user.name', _('Git Fusion Machinery'))
    _ensure_git_config_non_empty('user.email', _('*****@*****.**'))
예제 #22
0
def show_all_server_ids():
    '''List current Git Fusion server ids.'''

    server_ids = p4.run('counters', '-u', '-e',
                        p4gf_const.P4GF_COUNTER_SERVER_ID + '*')
    ids = []
    this_server = p4gf_util.read_server_id_from_file()
    for eyed in server_ids:
        if 'counter' in eyed:
            id_ = eyed['counter'].replace(p4gf_const.P4GF_COUNTER_SERVER_ID,
                                          '')
            if this_server == id_:
                id_ = "* " + id_
            ids.append((id_, eyed['value']))

    if ids:
        Verbosity.report(Verbosity.INFO,
                         _("Git Fusion server IDs: {0}").format(ids))
예제 #23
0
def ensure_protect(protect_lines):
    """Require that 'p4 protect' table includes grant of admin to git-fusion-user.
    And review to git-fusion-reviews-*
    """
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('protects', '-m', '-u', p4gf_const.P4GF_USER)

    if p4gf_p4msg.find_msgid(p4, p4gf_p4msgid.MsgDm_ProtectsEmpty):
        Verbosity.report(Verbosity.INFO, _("Protect table empty. Setting...."))

    l = None
    Verbosity.report(Verbosity.DEBUG,
                     NTR('p4 protects -mu git-fusion-user\n{}').format(r))
    perm = p4gf_util.first_value_for_key(r, KEY_PERM_MAX)
    if perm and perm in ['admin', 'super']:
        Verbosity.report(
            Verbosity.INFO,
            _("Protect table already grants 'admin' to user '{}'. Not changing"
              ).format(p4gf_const.P4GF_USER))
    else:
        l = protect_lines
        l.append('admin user {user} * //...'.format(user=p4gf_const.P4GF_USER))

    review_perm = 'review user git-fusion-reviews-* * //...'
    if review_perm in protect_lines:
        # Do not insert a newline into this line even
        # though it is long. Makes it too hard to test
        # in p4gf_super_init.t
        Verbosity.report(
            Verbosity.INFO,
            _("Protect table already grants 'review' to users 'git-fusion-reviews-*'."
              "Not changing"))
    else:
        if not l:
            l = protect_lines
        l.append(review_perm)

    if l:
        p4gf_util.set_spec(p4, 'protect', values={KEY_PROTECTIONS: l})
        Verbosity.report(
            Verbosity.INFO,
            _("Protect table modified. User '{}' granted admin permission.").
            format(p4gf_const.P4GF_USER))
예제 #24
0
def initialize_all_gf_reviews():
    """Execute p4gf_submit_trigger.py as super user to reset the
       git-fusion-reviews--all-gf reviews used by the submit trigger"""
    trigger_path = "{0}/{1}".format(
        os.path.dirname(os.path.abspath(sys.argv[0])), P4_TRIGGER_FILE)
    if not os.path.exists(trigger_path):
        print(_("Unable to find and execute '{0}'").format(trigger_path))
        return

    if P4USER == p4gf_const.P4GF_USER:
        # HACK: p4gf_submit_trigger.py script is hard-coded to ignore most
        # commands run by the git-fusion-user user, so issue a warning.
        print(
            _("Unable to rebuild the P4GF reviews as user '{}'.").format(
                P4USER))
        print(_("Please rebuild the P4GF reviews as another user."))
        return

    try:
        cmd = [trigger_path, '--rebuild-all-gf-reviews', P4PORT, P4USER]
        p = Popen(cmd, stdout=PIPE, stderr=PIPE)
        fd = p.communicate()
        # pylint: disable=E1101
        # Instance of '' has no '' member
        if p.returncode:
            print(
                _("Error '{ec}' returned from command '{cmd}'").format(
                    cmd=' '.join(cmd), ec=p.returncode))
            print("{0} {1}".format(str(fd[0]), str(fd[1])))
            return
    # pylint: disable=W0703
    # Catching too general exception
    except Exception:
        print(
            _("Error rebuilding all GF reviews, unable to locate and/or run '{0}'"
              ).format(trigger_path))
        return

    if len(fd[0]):
        Verbosity.report(
            Verbosity.INFO,
            _("Re-setting 'git-fusion-reviews--all-gf' with {0:d} repo views").
            format(len(fd[0].splitlines())))
예제 #25
0
def initialize_all_gf_reviews():
    """Execute p4gf_submit_trigger.py as super user to reset the
       git-fusion-reviews--all-gf reviews used by the submit trigger"""
    trigger_path = "{0}/{1}".format(os.path.dirname(os.path.abspath(sys.argv[0])),
                                    P4_TRIGGER_FILE)
    if not os.path.exists(trigger_path):
        print(_("Unable to find and execute '{trigger}'").format(trigger=trigger_path))
        return

    python = 'python3.3'
    try:
        cmd = [python, trigger_path, '--rebuild-all-gf-reviews', P4PORT, P4USER, "nocfg"]
        p = Popen(cmd, stdout=PIPE, stderr=PIPE)
        fd = p.communicate()
        if p.returncode:
            print(_("Error '{ec}' returned from command '{cmd}'")
                  .format(cmd=' '.join(cmd),
                          ec=p.returncode))
            out = fd[0] if isinstance(fd[0], str) else fd[0].decode()
            out = out.strip()
            err = fd[1] if isinstance(fd[1], str) else fd[1].decode()
            err = err.strip()
            if len(out):
                print(out)
            if len(err):
                print(err)
            if 'Perforce password (P4PASSWD) invalid or unset' in out+err:
                print(_("Ensure 'git-fusion-user' has a password and is logged in."))
                print(_("Then run this script again."))
            sys.exit(1)
    except Exception:   # pylint: disable=broad-except
        print(_("Error rebuilding all GF reviews, unable to locate "
                "and/or run '{python} {trigger}'").
              format(python=python, trigger=trigger_path))
        sys.exit(1)

    if len(fd[0]):
        Verbosity.report(
            Verbosity.INFO,
            _("Re-setting 'git-fusion-reviews--all-gf' with {num_views:d} repo views").
            format(num_views=len(fd[0].splitlines())))
예제 #26
0
def set_user_passwd_if_created(created, user):
    '''If creating the user, conditionally prompt for and set the passwd.'''
    global P4_PASSWD, PROMPT_FOR_PASSWD
    if created:
        if PROMPT_FOR_PASSWD:
            prompt_msg = _(
                "Set one password for Perforce users 'git-fusion-user'"
                "\nand 'git-fusion-reviews-*'.")
            # When creating additional Git Fusion instance only the new reviews will be created.
            # Catch this case and avoid a misleading prompt.
            if user == p4gf_util.gf_reviews_user_name():
                prompt_msg = _("Enter a new password for Perforce user '{0}'."
                               ).format(user)
            try:
                P4_PASSWD = get_passwd(prompt_msg)
            except KeyboardInterrupt:
                Verbosity.report(Verbosity.INFO,
                                 _("\n Stopping. Passwords not set."))
                sys.exit(1)
            # If we prompted, do so once and use for all the service users,
            # even if the user enters no password at all.
            PROMPT_FOR_PASSWD = False
            if not P4_PASSWD:
                Verbosity.report(Verbosity.INFO,
                                 _("Empty password. Not setting passwords."))

        # passwd may be suppressed with --nopasswd option, which also suppresses the prompt.
        if P4_PASSWD:
            set_passwd(user, P4_PASSWD)
            Verbosity.report(
                Verbosity.INFO,
                _("Password set for Perforce user '{}'.").format(user))
예제 #27
0
def set_user_passwd_if_created(created, user):
    '''If creating the user, conditionally prompt for and set the passwd.'''
    global P4_PASSWD, PROMPT_FOR_PASSWD
    if created:
        if PROMPT_FOR_PASSWD:
            prompt_msg = _("Set one password for Perforce users 'git-fusion-user'"
                           "\nand 'git-fusion-reviews-*'.")
            # When creating additional Git Fusion instance only the new reviews will be created.
            # Catch this case and avoid a misleading prompt.
            if user == p4gf_util.gf_reviews_user_name():
                prompt_msg = _("Enter a new password for Perforce user '{0}'.").format(user)
            try:
                P4_PASSWD = get_passwd(prompt_msg)
            except KeyboardInterrupt:
                Verbosity.report(Verbosity.INFO,
                    _("\n Stopping. Passwords not set."))
                sys.exit(1)
            # If we prompted, do so once and use for all the service users,
            # even if the user enters no password at all.
            PROMPT_FOR_PASSWD = False
            if not P4_PASSWD:
                Verbosity.report(Verbosity.INFO,
                    _("Empty password. Not setting passwords."))

        # passwd may be suppressed with --nopasswd option, which also suppresses the prompt.
        if P4_PASSWD:
            set_passwd(user, P4_PASSWD)
            Verbosity.report(Verbosity.INFO,
                    _("Password set for Perforce user '{}'.").format(user))
예제 #28
0
def ensure_protect(protect_lines):
    """Require that 'p4 protect' table includes grant of admin to git-fusion-user.
    And review to git-fusion-reviews-*
    """
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('protects', '-m', '-u', p4gf_const.P4GF_USER)

    if p4gf_p4msg.find_msgid(p4, p4gf_p4msgid.MsgDm_ProtectsEmpty):
        Verbosity.report(Verbosity.INFO, _("Protect table empty. Setting...."))

    l = None
    Verbosity.report(Verbosity.DEBUG, NTR('p4 protects -mu git-fusion-user\n{}').format(r))
    perm = p4gf_util.first_value_for_key(r, KEY_PERM_MAX)
    if perm and perm in ['admin', 'super']:
        Verbosity.report(Verbosity.INFO,
                         _("Protect table already grants 'admin' to user '{}'. Not changing")
                         .format(p4gf_const.P4GF_USER))
    else:
        l = protect_lines
        l.append('admin user {user} * //...'.format(user=p4gf_const.P4GF_USER))

    review_perm = 'review user git-fusion-reviews-* * //...'
    if review_perm in protect_lines:
                        # Do not insert a newline into this line even
                        # though it is long. Makes it too hard to test
                        # in p4gf_super_init.t
        Verbosity.report(Verbosity.INFO,
            _("Protect table already grants 'review' to users 'git-fusion-reviews-*'."
              "Not changing"))
    else:
        if not l:
            l = protect_lines
        l.append(review_perm)

    if l:
        p4gf_util.set_spec(p4, 'protect', values={KEY_PROTECTIONS : l})
        Verbosity.report(Verbosity.INFO,
                _("Protect table modified. User '{}' granted admin permission.")
                .format(p4gf_const.P4GF_USER))
예제 #29
0
def initialize_all_gf_reviews():
    """Execute p4gf_submit_trigger.py as super user to reset the
       git-fusion-reviews--all-gf reviews used by the submit trigger"""
    trigger_path = "{0}/{1}".format(os.path.dirname(os.path.abspath(sys.argv[0])),
        P4_TRIGGER_FILE)
    if not os.path.exists(trigger_path):
        print(_("Unable to find and execute '{0}'").format(trigger_path))
        return

    if P4USER == p4gf_const.P4GF_USER:
        # HACK: p4gf_submit_trigger.py script is hard-coded to ignore most
        # commands run by the git-fusion-user user, so issue a warning.
        print(_("Unable to rebuild the P4GF reviews as user '{}'.").format(P4USER))
        print(_("Please rebuild the P4GF reviews as another user."))
        return

    try:
        cmd = [trigger_path, '--rebuild-all-gf-reviews', P4PORT, P4USER ]
        p = Popen(cmd, stdout=PIPE, stderr=PIPE)
        fd = p.communicate()
        # pylint: disable=E1101
        # Instance of '' has no '' member
        if p.returncode:
            print(_("Error '{ec}' returned from command '{cmd}'")
                   .format(cmd=' '.join(cmd),
                           ec=p.returncode))
            print("{0} {1}".format(str(fd[0]), str(fd[1])))
            return
    # pylint: disable=W0703
    # Catching too general exception
    except Exception:
        print(_("Error rebuilding all GF reviews, unable to locate and/or run '{0}'").
                format(trigger_path))
        return

    if len(fd[0]):
        Verbosity.report(Verbosity.INFO,
            _("Re-setting 'git-fusion-reviews--all-gf' with {0:d} repo views").
            format(len(fd[0].splitlines())))
예제 #30
0
def parse_argv():
    """Copy optional port/user args into global P4PORT/P4USER."""

    parser = p4gf_util.create_arg_parser(
    _("Creates Git Fusion user, depot, and protect entries."))
    parser.add_argument('--port',    '-p', metavar='P4PORT', nargs=1, help=_('P4PORT of server'))
    parser.add_argument('--user',    '-u', metavar='P4USER', nargs=1, help=_('P4USER of user with super permissions.'))
    Verbosity.add_parse_opts(parser)
    parser.add_argument('--id',                              nargs=1, help=_("Set this Git Fusion server's unique id"))
    parser.add_argument('--showids',            action='store_true',  help=_('Display all Git Fusion server ids'))
    parser.add_argument('--ignore-case',        action='store_true',  help=_('Do not check for case-handling policy in server.'))
    parser.add_argument('--force', action='store_true', help=_("Force set local server-id file when server-id already registered in Git Fusion."))
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--passwd',                              nargs=1, help=_("Password for 'git-fusion-user' and 'git-fusion-reviews-*'"))
    group.add_argument('--no-passwd',           action='store_true', help=_("Do not prompt for nor set password for 'git-fusion-user' and 'git-fusion-reviews-*'"))
    args = parser.parse_args()

    Verbosity.parse_level(args)

    # Optional args, None if left unset
    global P4PORT, P4USER, ID_FROM_ARGV, SHOW_IDS, P4_PASSWD, PROMPT_FOR_PASSWD
    global IGNORE_CASE_HANDLING, OVERRULE_SERVERID_CONFLICT
    if args.port:
        P4PORT = args.port[0]
    if args.user:
        P4USER = args.user[0]
    if args.id:
        ID_FROM_ARGV = args.id[0]
    if args.showids:
        SHOW_IDS = True
    if args.passwd:
        P4_PASSWD = args.passwd[0]
        PROMPT_FOR_PASSWD = False
    elif args.no_passwd:
        PROMPT_FOR_PASSWD = False
    if args.ignore_case:
        IGNORE_CASE_HANDLING = True
    if args.force:
        OVERRULE_SERVERID_CONFLICT = True
예제 #31
0
def parse_argv():
    """Copy optional port/user args into global P4PORT/P4USER."""
    # pylint:disable=line-too-long
    # Keep tabular code tabular.
    parser = p4gf_util.create_arg_parser(_("Creates Git Fusion users, depot, and protect entries."))
    parser.add_argument('--port',    '-p', metavar='P4PORT', nargs=1, help=_('P4PORT of server'))
    parser.add_argument('--user',    '-u', metavar='P4USER', nargs=1, help=_('P4USER of user with super permissions.'))
    Verbosity.add_parse_opts(parser)
    parser.add_argument('--id',                              nargs=1, help=_("Set this Git Fusion server's unique id"))
    parser.add_argument('--showids',            action='store_true',  help=_('Display all Git Fusion server ids'))
    parser.add_argument('--force', action='store_true', help=_("Force set local server-id file when server-id already registered in Git Fusion or change it to a new value if --id option is provided."))
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--passwd',                              nargs=1, help=_("Do not prompt for password, use PASSWD when creating new service users (ex. 'git-fusion-user' and 'git-fusion-reviews-*')"))
    group.add_argument('--no-passwd',           action='store_true', help=_("Do not prompt for nor set password when creating new service users (ex. 'git-fusion-user' and 'git-fusion-reviews-*')"))
    parser.add_argument('--unknown-git', action='store_true', help=_("Create the unknown_git user and if --passwd set passwd"))
    args = parser.parse_args()

    Verbosity.parse_level(args)

    # Optional args, None if left unset
    global P4PORT, P4USER, ID_FROM_ARGV, SHOW_IDS, P4_PASSWD, PROMPT_FOR_PASSWD
    global OVERRULE_SERVERID_CONFLICT, CREATE_UNKNOWN_GIT
    if args.port:
        P4PORT = args.port[0]
    if args.user:
        P4USER = args.user[0]
    if args.id:
        ID_FROM_ARGV = args.id[0]
    if args.showids:
        SHOW_IDS = True
    if args.passwd:
        P4_PASSWD = args.passwd[0]
        PROMPT_FOR_PASSWD = False
    elif args.no_passwd:
        PROMPT_FOR_PASSWD = False
    if args.force:
        OVERRULE_SERVERID_CONFLICT = True
    if args.unknown_git:
        CREATE_UNKNOWN_GIT = True
예제 #32
0
def _ensure_case_sensitive():
    """
    Ensure that the Perforce server is case sensitive, but only if we have
    not been instructed to ignore the issue completely, in which case it is
    assumed the administrator knows what they are doing.
    """
    if not IGNORE_CASE_HANDLING:
        info = p4gf_util.first_dict(p4.run('info'))
        if not info.get('caseHandling') == 'sensitive':
            # Yes, the formatting is weird, but otherwise dedent and fill
            # will not yield the desired results (see job job070463).
            msg = _("""\
            The Perforce service's case-handling policy is not set to 'sensitive',
            which means any files introduced via Git whose names differ only by case may
            result in data loss or errors during push. It is strongly advised to set the
            case-handling policy to 'sensitive'. To bypass this check, pass --ignore-case
            when invoking this script.
            """)
            dims = shutil.get_terminal_size()
            msg = textwrap.fill(textwrap.dedent(msg), dims[0])
            Verbosity.report(Verbosity.ERROR, msg)
            sys.exit(1)
예제 #33
0
def show_all_server_ids():
    """List current Git Fusion server ids."""
    server_ids = P4Key.get_all(p4, p4gf_const.P4GF_P4KEY_SERVER_ID + '*')
    ids = []
    this_server = p4gf_util.read_server_id_from_file()
    for key, value in server_ids.items():
        id_ = key.replace(p4gf_const.P4GF_P4KEY_SERVER_ID, '')
        if this_server == id_:
            id_ = id_ + " *"
        ids.append((id_, value))

    if ids:
        Verbosity.report(
            Verbosity.INFO,
            _("Git Fusion server IDs:  {server_id: <30}   {hostname: <30}"
              "  (* marks this instance)")
            .format(server_id="server-id", hostname="hostname"))
        for sid in ids:
            Verbosity.report(
                Verbosity.INFO,
                _("                        {server_id: <30}   {hostname: <30}")
                .format(server_id=sid[0], hostname=sid[1]))
예제 #34
0
def ensure_users():
    """Create Perforce user git-fusion-user, and reviews users if not already extant."""
    default_auth_method = get_auth_method()
    has_auth_check, has_service_check = has_auth_check_trigger()
    set_perforce_auth_method = default_auth_method and default_auth_method != 'perforce'

    # These ensure_user-* methods always set AuthMethod to 'perforce'
    created = p4gf_p4spec.ensure_user_gf(p4, set_perforce_auth_method)
    log_user_info(created, has_auth_check, p4gf_const.P4GF_USER, default_auth_method)
    if not has_auth_check:
        set_passwd_and_login(created, p4gf_const.P4GF_USER)

    created = p4gf_p4spec.ensure_user_reviews(p4, set_perforce_auth_method)
    log_user_info(created, has_service_check, p4gf_util.gf_reviews_user_name(), default_auth_method)
    if not has_service_check:
        set_passwd_and_login(created, p4gf_util.gf_reviews_user_name())

    created = p4gf_p4spec.ensure_user_reviews_non_gf(p4, set_perforce_auth_method)
    log_user_info(created, has_service_check, p4gf_const.P4GF_REVIEWS__NON_GF, default_auth_method)
    if not has_service_check:
        set_passwd_and_login(created, p4gf_const.P4GF_REVIEWS__NON_GF)

    created = p4gf_p4spec.ensure_user_reviews_all_gf(p4, set_perforce_auth_method)
    log_user_info(created, has_service_check, p4gf_const.P4GF_REVIEWS__ALL_GF, default_auth_method)
    if not has_service_check:
        set_passwd_and_login(created, p4gf_const.P4GF_REVIEWS__ALL_GF)

    if CREATE_UNKNOWN_GIT:
        created = p4gf_p4spec.ensure_unknown_git(p4, set_perforce_auth_method)
        log_user_info(created, has_auth_check, p4gf_const.P4GF_UNKNOWN_USER, default_auth_method)
        if not has_auth_check:
            passwd = str(uuid.uuid4().hex).upper()[-10:] + '$#z'
            set_passwd_and_login(created, p4gf_const.P4GF_UNKNOWN_USER, passwd=passwd)

    # Report whether 'unknown_git' exists.
    e = p4gf_util.service_user_exists(p4, p4gf_const.P4GF_UNKNOWN_USER)
    _exists = ( _("Git Fusion user '{user}' does not exist.")
              , _("Git Fusion user '{user}' exists."))
    Verbosity.report(Verbosity.INFO, _exists[e].format(user=p4gf_const.P4GF_UNKNOWN_USER))
예제 #35
0
def set_passwd(user, passwd):
    """Set the P4 passwd for user. Assumes super user priviledge."""
    with p4.at_exception_level(p4.RAISE_NONE):
        p4.input = passwd
        r = p4.run_passwd(user)
        Verbosity.report(Verbosity.DEBUG, NTR('p4 passwd\n{}').format(r))
    if p4.errors:
        Verbosity.report(
            Verbosity.ERROR, _("Unable to run 'p4 passwd -P xxx {user}'.").format(user=user))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        Verbosity.report(
            Verbosity.ERROR,
            _("You must set passwords for Git Fusion users and re-run configure-git-fusion.sh"))
        Verbosity.report(
            Verbosity.ERROR,
            _("Git Fusion users are: {gf_user}  {reviews_user}  {non_gf}  {all_gf}")
            .format(gf_user=p4gf_const.P4GF_USER,
                    reviews_user=p4gf_util.gf_reviews_user_name(),
                    non_gf=p4gf_const.P4GF_REVIEWS__NON_GF,
                    all_gf=p4gf_const.P4GF_REVIEWS__ALL_GF))
        sys.exit(2)
예제 #36
0
def _ensure_case_sensitive():
    """
    Ensure that the Perforce server is case sensitive, but only if we have
    not been instructed to ignore the issue completely, in which case it is
    assumed the administrator knows what they are doing.
    """
    if not IGNORE_CASE_HANDLING:
        info = p4gf_util.first_dict(p4.run('info'))
        if not info.get('caseHandling') == 'sensitive':
            # Yes, the formatting is weird, but otherwise dedent and fill
            # will not yield the desired results (see job job070463).
            msg = _("""\
            The Perforce service's case-handling policy is not set to 'sensitive',
            which means any files introduced via Git whose names differ only by case may
            result in data loss or errors during push. It is strongly advised to set the
            case-handling policy to 'sensitive'. To bypass this check, pass --ignore-case
            when invoking this script.
            """)
            dims = shutil.get_terminal_size()
            msg = textwrap.fill(textwrap.dedent(msg), dims[0])
            Verbosity.report(Verbosity.ERROR, msg)
            sys.exit(1)
예제 #37
0
def ensure_users():
    """Create Perforce user git-fusion-user, and reviews users if not already extant."""
    created = p4gf_util.ensure_user_gf(p4)
    log_info(created, p4gf_const.P4GF_USER)
    set_user_passwd_if_created(created, p4gf_const.P4GF_USER)

    created = p4gf_util.ensure_user_reviews(p4)
    log_info(created, p4gf_util.gf_reviews_user_name())
    set_user_passwd_if_created(created, p4gf_util.gf_reviews_user_name())

    created = p4gf_util.ensure_user_reviews_non_gf(p4)
    log_info(created, p4gf_const.P4GF_REVIEWS__NON_GF)
    set_user_passwd_if_created(created, p4gf_const.P4GF_REVIEWS__NON_GF)

    created = p4gf_util.ensure_user_reviews_all_gf(p4)
    log_info(created, p4gf_const.P4GF_REVIEWS__ALL_GF)
    set_user_passwd_if_created(created, p4gf_const.P4GF_REVIEWS__ALL_GF)

    # Report whether 'unknown_git' exists. Do not create.
    e = p4gf_util.service_user_exists(p4, p4gf_const.P4GF_UNKNOWN_USER)
    _exists = ( _("Git Fusion user '{0}' does not exist.")
              , _("Git Fusion user '{0}' exists."))
    Verbosity.report(Verbosity.INFO, _exists[e].format(p4gf_const.P4GF_UNKNOWN_USER))
예제 #38
0
def check_triggers():
    """Check all of the GF triggers are installed and the trigger version is correct."""
    # pylint: disable=too-many-branches
    triggers = fetch_triggers()
    if not triggers:
        Verbosity.report(Verbosity.INFO, _('Git Fusion Triggers are not installed.'))
        return

    # Do we have a "p4gf_submit_trigger.py change-blah" entry for each
    # of the P4_TRIGGER_NAMES that we expect? If so, then the trigger
    # is fully installed.
    seen = set()
    for trig in triggers:
        if "p4gf_submit_trigger.py" not in trig:
            continue
        for tn in P4_TRIGGER_NAMES:
            if tn in trig:
                seen.add(tn)
    have_all_triggers = seen.issuperset(P4_TRIGGER_NAMES)
    if not have_all_triggers:
        Verbosity.report(Verbosity.INFO, _('Git Fusion Triggers are not installed.'))
        return

    # Is the installed version what we require?
    version = P4Key.get(p4, p4gf_const.P4GF_P4KEY_TRIGGER_VERSION)
    if version != '0':
        version = version.split(":")[0].strip()
    if version != p4gf_const.P4GF_TRIGGER_VERSION:
        Verbosity.report(Verbosity.INFO, _('Git Fusion Triggers are not up to date.'))
        Verbosity.report(Verbosity.INFO,
            _('This version of Git Fusion expects p4 key {key}={value}')
            .format(key=p4gf_const.P4GF_P4KEY_TRIGGER_VERSION,
                    value=p4gf_const.P4GF_TRIGGER_VERSION))
        return
    else:
        Verbosity.report(Verbosity.INFO, _('Git Fusion triggers are up to date.'))
        return
예제 #39
0
def ensure_users():
    """Create Perforce user git-fusion-user, and reviews users if not already extant."""
    created = p4gf_util.ensure_user_gf(p4)
    log_info(created, p4gf_const.P4GF_USER)
    set_user_passwd_if_created(created, p4gf_const.P4GF_USER)

    created = p4gf_util.ensure_user_reviews(p4)
    log_info(created, p4gf_util.gf_reviews_user_name())
    set_user_passwd_if_created(created, p4gf_util.gf_reviews_user_name())

    created = p4gf_util.ensure_user_reviews_non_gf(p4)
    log_info(created, p4gf_const.P4GF_REVIEWS__NON_GF)
    set_user_passwd_if_created(created, p4gf_const.P4GF_REVIEWS__NON_GF)

    created = p4gf_util.ensure_user_reviews_all_gf(p4)
    log_info(created, p4gf_const.P4GF_REVIEWS__ALL_GF)
    set_user_passwd_if_created(created, p4gf_const.P4GF_REVIEWS__ALL_GF)

    # Report whether 'unknown_git' exists. Do not create.
    e = p4gf_util.service_user_exists(p4, p4gf_const.P4GF_UNKNOWN_USER)
    _exists = (_("Git Fusion user '{0}' does not exist."),
               _("Git Fusion user '{0}' exists."))
    Verbosity.report(Verbosity.INFO,
                     _exists[e].format(p4gf_const.P4GF_UNKNOWN_USER))
예제 #40
0
def set_passwd(user, passwd):
    '''Set the P4 passwd for user. Assumes super user priviledge.'''
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('passwd', '-P', passwd, user)
        Verbosity.report(Verbosity.DEBUG, NTR('p4 passwd\n{}').format(r))
    if p4.errors:
        Verbosity.report(Verbosity.ERROR
                        , _("Unable to run 'p4 passwd -P xxx -u {0}'.").format(user))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)
예제 #41
0
def init(p4):
    """Ensure both global and host-specific initialization are completed.
    """
    started_counter = p4gf_const.P4GF_COUNTER_INIT_STARTED
    complete_counter = p4gf_const.P4GF_COUNTER_INIT_COMPLETE
    if not old_counter_present(p4):
        Verbosity.report(Verbosity.DEBUG, _('Old 2012.2 counter not present.'))
    if not _maybe_perform_init(p4, started_counter, complete_counter, _global_init):
        Verbosity.report(Verbosity.INFO, _('Permissions already initialized. Not changing.'))
    server_id = p4gf_util.get_server_id()
    started_counter = p4gf_const.P4GF_COUNTER_INIT_STARTED + '-' + server_id
    complete_counter = p4gf_const.P4GF_COUNTER_INIT_COMPLETE + '-' + server_id
    p4gf_dir = p4gf_const.P4GF_HOME
    client_name = p4gf_util.get_object_client_name()

    def client_init(p4):
        '''Perform host-specific initialization (and create sample usermap).'''
        # Set up the host-specific client.
        _create_client(p4, client_name, p4gf_dir)
        # Ensure the default user map and global config files are in place.
        _write_user_map(p4, client_name, p4gf_dir)
        p4gf_config.create_file_global(p4)
        _delete_old_init_counters(p4, server_id)

    if not _maybe_perform_init(p4, started_counter, complete_counter, client_init):
        Verbosity.report(Verbosity.INFO, _('Client and usermap already initialized. Not changing.'))

        # If client already created, make sure it hasn't been tweaked.
        ###: do we really need to handle this case? this is here just to pass the tests
        view = ['//{depot}/... //{client}/...'.format(depot=p4gf_const.P4GF_DEPOT,
                client=client_name)]
        p4gf_util.ensure_spec_values(p4, 'client', client_name,
                {'Root': p4gf_dir, 'View': view})

    # Perform any necessary upgrades within a "lock" to avoid race conditions.
    # For now, the lock is global, but could conceivably loosen to host-only.
    started_counter = p4gf_const.P4GF_COUNTER_UPGRADE_STARTED
    complete_counter = p4gf_const.P4GF_COUNTER_UPGRADE_COMPLETE
    if not _maybe_perform_init(p4, started_counter, complete_counter, _upgrade_p4gf):
        Verbosity.report(Verbosity.INFO, _('Global config file already initialized. Not changing.'))

    # Require non-empty Git config user.name and user.email.
    _ensure_git_config_non_empty('user.name',  _('Git Fusion Machinery'))
    _ensure_git_config_non_empty('user.email', _('*****@*****.**'))
예제 #42
0
def set_passwd(user, passwd):
    '''Set the P4 passwd for user. Assumes super user priviledge.'''
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('passwd', '-P', passwd, user)
        Verbosity.report(Verbosity.DEBUG, NTR('p4 passwd\n{}').format(r))
    if p4.errors:
        Verbosity.report(
            Verbosity.ERROR,
            _("Unable to run 'p4 passwd -P xxx -u {0}'.").format(user))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)
예제 #43
0
def ensure_group():
    """Create Perforce group git-fusion-group if not already exists."""
    users = []
    # Keep the order of the users in the same order that P4 insists on
    # (if the order doesn't match then the group is updated repeatedly).
    users.append(p4gf_const.P4GF_REVIEWS__ALL_GF)
    users.append(p4gf_const.P4GF_REVIEWS__NON_GF)
    users.append(p4gf_util.gf_reviews_user_name())
    users.append(p4gf_const.P4GF_USER)
    args = [p4, NTR("group")]
    spec = {'Timeout': NTR('unlimited'), 'Users': users}
    kwargs = {'spec_id': p4gf_const.P4GF_GROUP, 'values': spec}
    if not p4gf_util.ensure_spec(*args, **kwargs):
        # We change the list of users in the group from time to time,
        # so ensure the membership is up to date.
        users = p4gf_util.first_dict(
            p4.run('group', '-o', p4gf_const.P4GF_GROUP))['Users']
        # Add the gf_reviews_user_name if not already in the group.
        # This avoids removing already existing reviews users from multiple GF instances.
        if not p4gf_util.gf_reviews_user_name() in users:
            users.append(p4gf_util.gf_reviews_user_name())
            spec = {'Timeout': NTR('unlimited'), 'Users': users}
            kwargs = {'spec_id': p4gf_const.P4GF_GROUP, 'values': spec}
            if p4gf_util.ensure_spec_values(*args, **kwargs):
                Verbosity.report(
                    Verbosity.INFO,
                    _("Group '{}' updated.").format(p4gf_const.P4GF_GROUP))
            else:
                Verbosity.report(
                    Verbosity.INFO,
                    _("Group '{}' already up to date.").format(
                        p4gf_const.P4GF_GROUP))
        else:
            Verbosity.report(
                Verbosity.INFO,
                _("Group '{}' already up to date.").format(
                    p4gf_const.P4GF_GROUP))
        return False
    else:
        Verbosity.report(
            Verbosity.INFO,
            _("Group '{}' created.").format(p4gf_const.P4GF_GROUP))
    return True
예제 #44
0
def fetch_protect():
    """Return protect table as a list of protect lines."""
    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('protect', '-o')
        Verbosity.report(Verbosity.DEBUG, NTR('p4 protect:\n{result}').format(result=r))
    if p4.errors:
        Verbosity.report(Verbosity.ERROR, _("Unable to run 'p4 protect -o'."))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)

    protections = p4gf_util.first_value_for_key(r, KEY_PROTECTIONS)
    LOG.debug('retrieved protections: %s', protections)
    return protections
예제 #45
0
def fetch_protect():
    """Return protect table as a list of protect lines."""

    with p4.at_exception_level(p4.RAISE_NONE):
        r = p4.run('protect','-o')
        Verbosity.report(Verbosity.DEBUG, NTR('p4 protect:\n{}').format(r))
    if p4.errors:
        Verbosity.report(Verbosity.ERROR, _("Unable to run 'p4 protect -o'."))
        for e in p4.errors:
            Verbosity.report(Verbosity.ERROR, e)
        sys.exit(2)

    protections = p4gf_util.first_value_for_key(r, KEY_PROTECTIONS)
    return protections
예제 #46
0
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)
예제 #47
0
def check_and_create_default_p4gf_env_config():
    '''If p4gf_env_config threw the MissingConfigPath exception,
    because P4GF_ENV names a non-existing filepath
    then save the required (two) default items
    into the user configured P4GF_ENV environment config file.
    '''
    if not Create_P4GF_CONFIG:
        return
    Verbosity.report(Verbosity.INFO,
            _("Git Fusion environment var P4GF_ENV = {0} names a non-existing file.")
            .format(p4gf_const.P4GF_ENV))
    Verbosity.report(Verbosity.INFO, _("Creating {0} with the default required items.")
            .format(p4gf_const.P4GF_ENV))
    Verbosity.report(Verbosity.INFO, _("Review the file's comments and edit as needed."))
    Verbosity.report(Verbosity.INFO, _("You may unset P4GF_ENV to use no config file.")
            .format(p4gf_const.P4GF_ENV))
    config = configparser.ConfigParser(interpolation  = None,
                                       allow_no_value = True)
    config.optionxform = str
    config.add_section(p4gf_const.SECTION_ENVIRONMENT)
    config.set(p4gf_const.SECTION_ENVIRONMENT, p4gf_const.P4GF_HOME_NAME, p4gf_const.P4GF_HOME)
    Verbosity.report(Verbosity.INFO, _("Setting {0} = {1} in {2}.")
            .format(p4gf_const.P4GF_HOME_NAME, p4gf_const.P4GF_HOME, p4gf_const.P4GF_ENV))
    config.set(p4gf_const.SECTION_ENVIRONMENT, NTR('P4PORT'), P4PORT)
    Verbosity.report(Verbosity.INFO, _("Setting {0} = {1} in {2}.")
        .format(NTR('P4PORT'), P4PORT, p4gf_const.P4GF_ENV))
    header = p4gf_util.read_bin_file(NTR('p4gf_env_config.txt'))
    if header is False:
        sys.stderr.write(_('no p4gf_env_config.txt found\n'))
        header = _('# Missing p4gf_env_config.txt file!')
    out = io.StringIO()
    out.write(header)
    config.write(out)
    file_content = out.getvalue()
    out.close()
    p4gf_util.ensure_dir(p4gf_util.parent_dir(p4gf_const.P4GF_ENV))
    with open(p4gf_const.P4GF_ENV, 'w') as f:
        f.write(file_content)
예제 #48
0
def _info(msg):
    '''
    CLI output
    '''
    Verbosity.report(Verbosity.INFO, msg)
예제 #49
0
def ensure_server_id():
    """Write this machine's permanent server-id assignment to
    P4GF_HOME/server-id .

    NOP if we already have a server-id stored in that file.
    We'll just keep using it.
    """
    id_from_file = p4gf_util.read_server_id_from_file()

    server_id = ID_FROM_ARGV if ID_FROM_ARGV else p4gf_util.get_hostname()
    # when re-running super_init, do not replace the server-id file when
    # the server_id file exists an no --id parameter is present
    # assume in the case that the existing file is correct
    if id_from_file and not ID_FROM_ARGV:
        server_id = id_from_file

    do_reset = True
    if server_id_counter_exists(server_id):
        do_reset = False
        if id_from_file == server_id:
            Verbosity.report(Verbosity.INFO,
                    _("Git Fusion server ID already set to '{0}'.").format(id_from_file))
        else:
            if not OVERRULE_SERVERID_CONFLICT:
                Verbosity.report(Verbosity.INFO,
                        _("Git Fusion server ID is already assigned: " \
                        "'{0}' set on host on '{1}'.\n" \
                        "Retry with a different --id server_id.") \
                        .format(server_id, server_id_counter_exists(server_id)))
                Verbosity.report(Verbosity.INFO,
                    _("If you are certain no other Git Fusion instance is using this server ID,"
                    "\nyou may overrule this conflict and set the local server-id file to"
                    "\n'{0}' with:"
                    "\n    p4gf_super_init.py --force").format(server_id))
                if id_from_file:
                    Verbosity.report(Verbosity.INFO,
                        _("Git Fusion server ID already set to '{0}'.").format(id_from_file))
                else:
                    Verbosity.report(Verbosity.INFO,
                        _("This Git Fusion's server ID is unset. Stopping."))
                    show_all_server_ids()
                    sys.exit(0)

            else:
                do_reset = True


    if do_reset:
        if id_from_file and id_from_file != server_id:  # delete the previous counter
            if server_id_counter_exists(id_from_file):
                unset_server_id_counter(id_from_file)
        set_server_id_counter(server_id)
        p4gf_util.write_server_id_to_file(server_id)
        Verbosity.report(Verbosity.INFO, _("Git Fusion server ID set to '{0}' in file '{1}'")
                         .format(server_id, p4gf_util.server_id_file_path()))
    show_all_server_ids()
예제 #50
0
def parse_argv():
    """Only version, help options for now"""
    parser = p4gf_util.create_arg_parser(_('Initializes a Git Fusion server.'))
    Verbosity.add_parse_opts(parser)
    args = parser.parse_args()
    Verbosity.parse_level(args)
예제 #51
0
    p4gf_util.ensure_dir(p4gf_util.parent_dir(p4gf_const.P4GF_ENV))
    with open(p4gf_const.P4GF_ENV, 'w') as f:
        f.write(file_content)

# p4gf_env_config will apply the config set by P4GF_ENV,
# but throw an exception if the P4GF_ENV is defined but the path does not exist.
# super_init will catch this exception and write the defaults to the P4GF_ENV path.
# pylint: disable=W0703
# Catching too general exception Exception
#
try:
    import p4gf_env_config    # pylint: disable=W0611
except MissingConfigPath:
    Create_P4GF_CONFIG = True
except Exception as exc:
    Verbosity.report(Verbosity.ERROR, str(exc))
    sys.exit(2)


# pylint: enable=W0703

def get_passwd(msg):
    '''Prompt for and confirm password.'''
    print("\n")
    if msg:
        print(msg)
    pw1 = NTR('pw1')
    pw2 = NTR('pw2')
    while pw1 != pw2:
        print(_("To cancel: CTL-C + ENTER."))
        pw1 = getpass.getpass(_('Password: '))
예제 #52
0
def check_triggers():
    """ Check all of the GF triggers are installed and the
    trigger version is correct.
    """
    # pylint: disable=R0912
    # Too many branches
    triggers = fetch_triggers()
    if not triggers:
        Verbosity.report(Verbosity.INFO,
            'Git Fusion Triggers are not installed.')
        return

    gf_triggers = set()
    for trig in triggers:
        words = trig.split()
        if P4_TRIGGER_FILE in trig:
            gf_triggers.add(words[5])

    have_all_triggers = 0
    if p4gf_version.p4d_version(p4) <  P4D_VERSION_2014_1:
        trigger_names = P4_TRIGGER_NAMES
    else:
        trigger_names = P4_TRIGGER_NAMES_14

    for trig in trigger_names:
        if trig in gf_triggers:
            have_all_triggers += 1

    if have_all_triggers == 0:
        Verbosity.report(Verbosity.INFO,
            'Git Fusion Triggers are not installed.')
    elif have_all_triggers < 4:
        Verbosity.report(Verbosity.INFO,
            'Git Fusion Triggers are not all installed.')
    else:   # check counter
        counter = p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION)[0]
        version = counter['value']
        if version != '0':
            version = version.split(":")[0].strip()
        version = int(version)
        if version and version != int(p4gf_const.P4GF_TRIGGER_VERSION):
            Verbosity.report(Verbosity.INFO,
                'Git Fusion Triggers are not up to date.')
        elif not version:
            # set the version counter since we detected
            # that all the triggers are installed
            _version = "{0} : {1}".format(p4gf_const.P4GF_TRIGGER_VERSION, datetime.datetime.now())
            p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION, _version)
            p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_POST_TRIGGER_VERSION, _version)
            Verbosity.report(Verbosity.INFO,
                _("Setting '{0}' = '{1}'").format(
                p4gf_const.P4GF_COUNTER_PRE_TRIGGER_VERSION, _version))
            Verbosity.report(Verbosity.INFO,
                _("Setting '{0}' = '{1}'").format(
                p4gf_const.P4GF_COUNTER_POST_TRIGGER_VERSION, _version))
        else:
            Verbosity.report(Verbosity.INFO,
                _('Git Fusion triggers are up to date.'))
예제 #53
0
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)