def create_repo_client(p4, view_name, client_name, client_root, view, stream):
    '''Create a Git Fusion repo client.'''
    desc = (_("Created by Perforce Git Fusion for work in '{view}'.").format(
        view=p4gf_translate.TranslateReponame.repo_to_git(view_name)))
    # if creating from a stream, set 'Stream' but not 'View'
    # otherwise, set 'View' but not 'Stream'
    if stream:
        p4gf_util.set_spec(p4,
                           'client',
                           spec_id=client_name,
                           values={
                               'Owner': p4gf_const.P4GF_USER,
                               'LineEnd': NTR('unix'),
                               'Root': client_root,
                               'Options': CLIENT_OPTIONS,
                               'Host': None,
                               'Stream': stream,
                               'Description': desc
                           })
    else:
        p4gf_util.set_spec(p4,
                           'client',
                           spec_id=client_name,
                           values={
                               'Owner': p4gf_const.P4GF_USER,
                               'LineEnd': NTR('unix'),
                               'View': view,
                               'Root': client_root,
                               'Options': CLIENT_OPTIONS,
                               'Host': None,
                               'Description': desc
                           })

    LOG.debug("Successfully created Git Fusion client %s", client_name)
Esempio n. 2
0
def create_repo_client(p4, view_name, client_name, client_root, view, stream):
    '''Create a Git Fusion repo client.'''
    desc = (_("Created by Perforce Git Fusion for work in '{view}'.")
            .format(view=p4gf_translate.TranslateReponame.repo_to_git(view_name)))
    # if creating from a stream, set 'Stream' but not 'View'
    # otherwise, set 'View' but not 'Stream'
    if stream:
        p4gf_util.set_spec(p4, 'client', spec_id=client_name,
                         values={'Owner'         : p4gf_const.P4GF_USER,
                                 'LineEnd'       : NTR('unix'),
                                 'Root'          : client_root,
                                 'Options'       : CLIENT_OPTIONS,
                                 'Host'          : None,
                                 'Stream'        : stream,
                                 'Description'   : desc})
    else:
        p4gf_util.set_spec(p4, 'client', spec_id=client_name,
                         values={'Owner'         : p4gf_const.P4GF_USER,
                                 'LineEnd'       : NTR('unix'),
                                 'View'          : view,
                                 'Root'          : client_root,
                                 'Options'       : CLIENT_OPTIONS,
                                 'Host'          : None,
                                 'Description'   : desc})

    LOG.debug("Successfully created Git Fusion client %s", client_name)
def ensure_protect(protect_lines):
    """Require that 'p4 protect' table includes grant of admin to git-fusion-user.

    """
    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):
        report(INFO, "Protect table empty. Setting....")

    report(DEBUG, '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']:
        report(INFO, ( "Protect table already grants 'admin'"
                     + " to user {}. Not changing").format(p4gf_const.P4GF_USER))
        return False

    l = protect_lines
    if p4gf_version.p4d_version_supports_admin_user(p4):
        perm = 'admin'
    else:
        perm = 'super'
    l.append('{perm} user {user} * //...'.format(perm=perm, user=p4gf_const.P4GF_USER))

    p4gf_util.set_spec(p4, 'protect', values={KEY_PROTECTIONS : l})
    report(INFO, "Protect table modified. {} granted admin permission."
                 .format(p4gf_const.P4GF_USER))
    return True
def ensure_protect(protect_lines):
    """Require that 'p4 protect' table includes grant of admin to git-fusion-user.

    """
    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):
        report(INFO, "Protect table empty. Setting....")

    report(DEBUG, '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']:
        report(INFO,
               ("Protect table already grants 'admin'" +
                " to user {}. Not changing").format(p4gf_const.P4GF_USER))
        return False

    l = protect_lines
    if p4gf_version.p4d_version_supports_admin_user(p4):
        perm = 'admin'
    else:
        perm = 'super'
    l.append('{perm} user {user} * //...'.format(perm=perm,
                                                 user=p4gf_const.P4GF_USER))

    p4gf_util.set_spec(p4, 'protect', values={KEY_PROTECTIONS: l})
    report(
        INFO, "Protect table modified. {} granted admin permission.".format(
            p4gf_const.P4GF_USER))
    return True
Esempio n. 5
0
def _global_init(p4):
    """Create global Git Fusion Perforce data:
    * user git-fusion-user
    * depot //.git-fusion
    * 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).
    #

    with p4gf_group.PermErrorOK(p4):
        p4gf_util.ensure_user_gf(p4)

    with p4gf_group.PermErrorOK(p4):
        p4gf_util.ensure_depot_gf(p4)

    p4gf_group.create_global_perm(p4, p4gf_group.PERM_PULL)
    p4gf_group.create_global_perm(p4, p4gf_group.PERM_PUSH)
    p4gf_group.create_default_perm(p4)

    ### ONCE ADMIN works, downgrade our auto-generated Protections
    ### table to git-fusion-user=admin, not super, and user * = write.

    # Require that single git-fusion-user have admin privileges
    # over the //.git-fusion/ depot
    is_protects_empty = False
    try:
        ### ONCE ADMIN works, remove the use of -u option
        p4.run('protects', '-u', p4gf_const.P4GF_USER, '-m',
               '//{depot}/...'.format(depot=p4gf_const.P4GF_DEPOT))
    except P4.P4Exception:
        if p4gf_p4msg.find_msgid(p4, p4gf_p4msgid.MsgDm_ProtectsEmpty):
            is_protects_empty = True
        # All other errors are fatal, propagated.

    if is_protects_empty:
        ### ONCE ADMIN works, modify the protects table as follows
        # - 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)]})
Esempio n. 6
0
def _repo_from_stream(p4, view_name, stream_name, client_name,
                      client_root, enable_mismatched_rhs, handle_imports=True):
    """Create a new client from the named stream.

    Create a new Perforce client spec <client_name> using existing Perforce
    stream spec <stream_name> as a template (just use its View).

    Returns one of the INIT_REPO_* constants.

    """
    # stream_name      is the name of a stream, e.g. '//depot/stream'
    # view_name        is the gfinternal repo name

    if not p4gf_util.spec_exists(p4, 'stream', stream_name):
        return INIT_REPO_NOVIEW

    with Validator.from_stream(view_name, p4, stream_name) as validator:
        if not validator.is_valid(enable_mismatched_rhs):
            return INIT_REPO_CONFIG_FILE_BAD

    # Seed a new client using the stream's view as a template.
    LOG.info("Git Fusion client %s does not exist, creating from existing Perforce stream %s",
             client_name, stream_name)

    # Create virtual stream with excluded paths, use that for client.
    stream = p4.fetch_stream(stream_name)
    if handle_imports:
        config = p4gf_config.get_repo(p4, view_name)
        imports_enabled = p4gf_config.is_feature_enabled(config, p4gf_config.FEATURE_IMPORTS)
    else:
        imports_enabled = False
    if imports_enabled:
        stream_paths = p4gf_streams.stream_import_exclude(stream['Paths'])
    else:
        stream_paths = stream['Paths']
    desc = (_("Created by Perforce Git Fusion for work in '{view}'.")
            .format(view=p4gf_translate.TranslateReponame.repo_to_git(view_name)))
    spec_values = {
        'Owner': p4gf_const.P4GF_USER,
        'Parent': stream_name,
        'Type': 'virtual',
        'Description': desc,
        'Options': 'notoparent nofromparent',
        'Paths': stream_paths,
        'Remapped': ['.gitmodules-{} .gitmodules'.format(view_name)]
    }
    if imports_enabled:
        stream_name += '_p4gfv'
        p4gf_util.set_spec(p4, 'stream', spec_id=stream_name, values=spec_values)
        LOG.debug('virtual stream {} created for {}'.format(stream_name, client_name))
    create_repo_client(p4, view_name, client_name, client_root, None, stream_name)

    return INIT_REPO_OK
 def switch_client_to_stream(self, branch):
     """
     Change this repo's Perforce client view to the branch's stream.
     """
     # Lazy create our read-perm client for streams
     if not self.p4client_created:
         p4gf_util.set_spec(
                             self.p4, 'client'
                           , spec_id = self.p4client
                           , cached_vardict = None)
         self.p4client_created = True
     self.p4run(['client', '-f', '-s', '-S', branch.stream_name, self.p4client])
 def switch_client_view_lines(self, lines):
     """
     Change this repo's Perforce client view to the given line list.
     """
     LOG.debug("switch_client_view_lines {0}".format(lines))
     _lines = p4gf_context.to_lines(lines)
     p4gf_util.set_spec(
                         self.p4, 'client'
                       , spec_id = self.p4client
                       , values  = {'View': _lines, 'Stream': None}
                       , cached_vardict = None)
     self.p4client_created = True
def create_p4_client(p4, view_name, client_name, client_root):
    """Create the p4 client to contain Git meta-data mirror.

    Keyword arguments:
    p4          -- Perforce client API
    view_name   -- client view of repository to clone
    client_name -- client that will be created
    client_root -- path for client workspace

    Returns one of the INIT_REPO_* constants.
    """
    # Ensure the client root directory has been created.
    if not os.path.exists(client_root):
        os.makedirs(client_root)

    # If a client for this view already exists, we're probably done.
    #
    # Make sure the client root is correct.
    if p4gf_util.spec_exists(p4, 'client', client_name):
        LOG.debug("%s client already exists for %s", client_name, view_name)
        p4gf_util.ensure_spec_values(p4, 'client', client_name, {'Root':client_root})
        return INIT_REPO_EXISTS

    # Client does not yet exist. We'll have to configure it manually, using
    # the view's name as a template.
    if not p4gf_util.spec_exists(p4, 'client', view_name):
        LOG.warn("requested client %s does not exist, required for creating a mirror", view_name)
        sys.stderr.write("View {} does not exist\n".format(view_name))
        return INIT_REPO_NOVIEW

    # Seed a new client using the view's view as a template.
    LOG.info("client %s does not exist, creating from view %s", client_name, view_name)

    view = p4gf_util.first_value_for_key(
            p4.run('client', '-o', '-t', view_name, client_name),
            'View')

    if not view_depots_ok(p4, view_name, view):
        # nature of problem already reported
        return INIT_REPO_BADVIEW

    desc = ("Created by Perforce Git Fusion for work in {view}."
            .format(view=view_name))
    p4gf_util.set_spec(p4, 'client', spec_id=client_name,
                     values={'Owner'         : p4gf_const.P4GF_USER,
                             'LineEnd'       : 'unix',
                             'View'          : view,
                             'Root'          : client_root,
                             'Host'          : None,
                             'Description'   : desc})
    LOG.debug("successfully created client %s", client_name)
    return INIT_REPO_OK
 def switch_client_to_stream(self, branch):
     """
     Change this repo's Perforce client view to the branch's stream.
     """
     # Lazy create our read-perm client for streams
     if not self.p4client_created:
         p4gf_util.set_spec(self.p4,
                            'client',
                            spec_id=self.p4client,
                            cached_vardict=None)
         self.p4client_created = True
     self.p4run(
         ['client', '-f', '-s', '-S', branch.stream_name, self.p4client])
 def switch_client_view_lines(self, lines):
     """
     Change this repo's Perforce client view to the given line list.
     """
     LOG.debug("switch_client_view_lines {0}".format(lines))
     _lines = p4gf_context.to_lines(lines)
     p4gf_util.set_spec(self.p4,
                        'client',
                        spec_id=self.p4client,
                        values={
                            'View': _lines,
                            'Stream': None
                        },
                        cached_vardict=None)
     self.p4client_created = True
Esempio n. 12
0
    def switch_client_view_lines(self, lines):
        """Change this repo's Perforce client view to the given line list.

        Update our clientmap object, with the new lines. Update clientmap in
        place so that other object with pointers to OUR clientmap object will
        see the new data.
        """
        _lines = to_lines(lines)
        if _lines == self.last_view_lines:
            LOG.debug2('switch_client_view_lines() already switched. NOP.')
            return

        LOG.debug2('switch_client_view_lines() client={} {}'.format(
            self.config.p4client, _lines))
        self.last_client_spec = p4gf_util.set_spec(
            self.p4,
            'client',
            spec_id=self.config.p4client,
            values={
                'View': _lines,
                'Stream': None
            },
            cached_vardict=self.last_client_spec)
        self.clientmap.clear()
        for line in _lines:
            self.clientmap.insert(line)
        self.last_view_lines = copy.copy(_lines)
Esempio n. 13
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))
Esempio n. 14
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))
Esempio n. 15
0
def update_repo_reviews(p4_reviews, user, clientmap, action=None, change=None):
    """Add or remove view left maps to the review user Reviews.
    Using Map.join, check for a conflict with self - this gf_reviews user.
    This check handles the case of overlapping views pushed to the same GF server.
    If conflict, return INTERSECT and do not update the user reviews
    """

    if clientmap:
        repo_views = clientmap.lhs()
    LOG.debug3("clientmap  = {}".format(clientmap))

    args_ = ['-o', user]
    r = p4_reviews.run('user', args_)
    vardict = p4gf_util.first_dict(r)
    current_reviews = []
    if "Reviews" in vardict:
        current_reviews = vardict["Reviews"]
        if action == ADD:
            if has_intersecting_views(current_reviews, clientmap):
                return INTERSECT

    if action == ADD:
        reviews = current_reviews + repo_views
    elif action == REMOVE:
        if user == p4gf_const.P4GF_REVIEWS__NON_GF:
            reviews = remove_non_gf_changelist_files(change, current_reviews)
        else:  # for Git Fusion reviews
            reviews = list(current_reviews)  # make a copy
            for path in repo_views:
                try:
                    reviews.remove(path)
                except ValueError:
                    pass
    else:
        raise RuntimeError(_("Git Fusion: update_repo_reviews incorrect action '{}'")
                           .format(action))
    LOG.debug3("for user {} setting reviews {}".format(user, reviews))
    p4gf_util.set_spec(p4_reviews, 'user', user, values={"Reviews": reviews})
    return NO_INTERSECT
    def _create_client_for_view_lines(self, view_lines):
        '''
        Create a new client spec with the requested view_lines.

        Return its name.
        '''
        client_name = self._generate_client_name()

        # Let client root match the real ctx.p4's client so that server-
        # calculated local paths match. Might come in handy.
        client_root = self.ctx.contentlocalroot

        desc = (_("Created by Perforce Git Fusion for queries in '{view}'.").
                format(view=self.ctx.config.view_name))

        # Replae RHS lines with new client name.
        new_view_map = p4gf_branch.replace_client_name(
            view_lines, self.ctx.config.p4client, client_name)

        if LOG.isEnabledFor(logging.DEBUG3):
            LOG.debug3(
                '_create_client_for_view_lines() name={} view={}'.format(
                    client_name, new_view_map.as_array()))
        else:
            LOG.debug2(
                '_create_client_for_view_lines() name={}'.format(client_name))
        p4gf_util.set_spec(self.ctx.p4gf,
                           'client',
                           spec_id=client_name,
                           values={
                               'Owner': p4gf_const.P4GF_USER,
                               'LineEnd': NTR('unix'),
                               'View': new_view_map.as_array(),
                               'Root': client_root,
                               'Host': None,
                               'Description': desc
                           })
        return client_name
Esempio n. 17
0
    def switch_client_view_lines(self, lines):
        """Change this repo's Perforce client view to the given line list.

        Update our clientmap object, with the new lines. Update clientmap in
        place so that other object with pointers to OUR clientmap object will
        see the new data.
        """
        _lines = to_lines(lines)
        if _lines == self.last_view_lines:
            LOG.debug2('switch_client_view_lines() already switched. NOP.')
            return

        LOG.debug2('switch_client_view_lines() client={} {}'
                  .format(self.config.p4client, _lines))
        self.last_client_spec = p4gf_util.set_spec(
                            self.p4, 'client'
                          , spec_id = self.config.p4client
                          , values  = {'View': _lines, 'Stream': None}
                          , cached_vardict = self.last_client_spec)
        self.clientmap.clear()
        for line in _lines:
            self.clientmap.insert(line)
        self.last_view_lines = copy.copy(_lines)
Esempio n. 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.'))
Esempio n. 19
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.'))
Esempio n. 20
0
def _repo_from_stream(p4,
                      view_name,
                      stream_name,
                      client_name,
                      client_root,
                      enable_mismatched_rhs,
                      handle_imports=True):
    """Create a new client from the named stream.

    Create a new Perforce client spec <client_name> using existing Perforce
    stream spec <stream_name> as a template (just use its View).

    Returns one of the INIT_REPO_* constants.

    """
    # stream_name      is the name of a stream, e.g. '//depot/stream'
    # view_name        is the gfinternal repo name

    if not p4gf_util.spec_exists(p4, 'stream', stream_name):
        return INIT_REPO_NOVIEW

    with Validator.from_stream(view_name, p4, stream_name) as validator:
        if not validator.is_valid(enable_mismatched_rhs):
            return INIT_REPO_CONFIG_FILE_BAD

    # Seed a new client using the stream's view as a template.
    LOG.info(
        "Git Fusion client %s does not exist, creating from existing Perforce stream %s",
        client_name, stream_name)

    # Create virtual stream with excluded paths, use that for client.
    stream = p4.fetch_stream(stream_name)
    if handle_imports:
        config = p4gf_config.get_repo(p4, view_name)
        imports_enabled = p4gf_config.is_feature_enabled(
            config, p4gf_config.FEATURE_IMPORTS)
    else:
        imports_enabled = False
    if imports_enabled:
        stream_paths = p4gf_streams.stream_import_exclude(stream['Paths'])
    else:
        stream_paths = stream['Paths']
    desc = (_("Created by Perforce Git Fusion for work in '{view}'.").format(
        view=p4gf_translate.TranslateReponame.repo_to_git(view_name)))
    spec_values = {
        'Owner': p4gf_const.P4GF_USER,
        'Parent': stream_name,
        'Type': 'virtual',
        'Description': desc,
        'Options': 'notoparent nofromparent',
        'Paths': stream_paths,
        'Remapped': ['.gitmodules-{} .gitmodules'.format(view_name)]
    }
    if imports_enabled:
        stream_name += '_p4gfv'
        p4gf_util.set_spec(p4,
                           'stream',
                           spec_id=stream_name,
                           values=spec_values)
        LOG.debug('virtual stream {} created for {}'.format(
            stream_name, client_name))
    create_repo_client(p4, view_name, client_name, client_root, None,
                       stream_name)

    return INIT_REPO_OK