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
Exemplo n.º 2
0
def _upgrade_p4gf(p4):
    """Perform upgrade from earlier versions of P4GF. This should be invoked
    using _maybe_perform_init() to avoid race conditions across hosts.
    """
    # If updating from 12.2 to 13.1 we need to create global config file
    # (this does nothing if file already exists)
    c = p4gf_config.create_file_global(p4)
    if c:
        _info(
            _("Global config file '{}' created.").format(
                p4gf_config.depot_path_global()))
    else:
        _info(
            _("Global config file '{}' already exists.").format(
                p4gf_config.depot_path_global()))
    # Ensure the time zone name has been set, else default to something sensible.
    r = p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME)
    tzname = p4gf_util.first_value_for_key(r, 'value')
    if tzname == "0" or tzname is None:
        msg = _("Counter '{}' not set, using UTC as default."          \
                " Change this to your Perforce server's time zone.") \
              .format(p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME)
        LOG.warn(msg)
        sys.stderr.write(NTR('Git Fusion: {}\n').format(msg))
        tzname = None
    else:
        # Sanity check the time zone name.
        try:
            pytz.timezone(tzname)
        except pytz.exceptions.UnknownTimeZoneError:
            LOG.warn("Time zone name '{}' unrecognized, using UTC as default".
                     format(tzname))
            tzname = None
    if tzname is None:
        p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME, 'UTC')
Exemplo n.º 3
0
 def release(self):
     """Release a previously acquired hold on the shared lock. Does nothing
     if the lock is not currently held by this instance.
     """
     if not self.__has:
         return
     counter_name = host_view_lock_name(self.__host_name, self.__view_name)
     shared_name = shared_host_view_name(self.__host_name, self.__view_name)
     with CounterLock(self.__p4, counter_name):
         current = p4gf_util.first_value_for_key(
                 self.__p4.run('counter', '-u', shared_name), 'value')
         if current and current != '0':
             # Remove our PID from the list of shared lock holders.
             value = self._lock_value()
             lines = current.splitlines()
             lines = [line for line in lines if line != value]
             value = '\n'.join(lines)
             if value:
                 self.__p4.run('counter', '-u', shared_name, value)
             else:
                 if self.__last_release_func:
                     self.__last_release_func()
                 try:
                     self.__p4.run('counter', '-u', '-d', shared_name)
                 except P4Exception:
                     LOG.warn("lock counter deletion failed: {}".format(shared_name))
     self.__has = False
Exemplo n.º 4
0
def repo_from_template_client( p4, view_name, view_name_p4client, client_name
                             , client_root, enable_mismatched_rhs):
    '''
    Create a new Perforce client spec <client_name> using existing Perforce
    client spec <view_name> as a template (just use its View).
    '''
    # view_name_p4client is the p4client
    # view_name        is the gfinternal repo name
    # view_name differs from view_name_p4client if latter contains special chars
    #           or was configured with --p4client argument


    if not p4gf_util.spec_exists(p4, 'client', view_name_p4client):
        return INIT_REPO_NOVIEW

    client = p4.run('client', '-o', view_name_p4client)[0]
    if 'Stream' in client:
        return _repo_from_stream(p4, view_name, client.get('Stream'),
                                 client_name, client_root, enable_mismatched_rhs)

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

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

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

    create_repo_client(p4, view_name, client_name, client_root, view, None)
    return INIT_REPO_OK
def _fetch(ctx):
    """If the Perforce server has a 'p4 typemap' configured, return it
    as a P4.Map instance.
    To accomodate mappings of multiple right-hand patterns to the same <type>
    append the <rhs> to the left hand <type>.
    Mapping will be unique, but require stripping the appended <rhs> postfix.
    If not, return None.
    """
    r = ctx.p4gfrun('typemap', '-o')
    raw_lines = p4gf_util.first_value_for_key(r, "TypeMap")
    if not raw_lines:
        return None

    typem = P4.Map()
    for mapline in raw_lines:
        lhs, sep, rhs = mapline.partition(
            ' ')  # the P4 typemap types are delimited by the first ' '
        # if <rhs> does not start with '/',
        # insert one when constructing new <lhs> = <type>/<rhs>
        # We dont care that '"' are embedded in the constructed new <lhs>
        # We do need to ensure that the <type> is followed immediately by a '/'
        # So we may append the <type> with the <rhs> as  <type><rhs> or <type>/<rhs>
        # and <rhs> may itself start with '/' or '"' or neither.
        # Our regex lookup will detect on the first '/'
        sep = ''  # concatenate <lhs><sep><rhs>
        if not rhs.startswith('/'):  # if there is no '/' .. then add '/'
            sep = '/'
        lhs = lhs + sep + rhs
        typem.insert(lhs, rhs)

    return typem
Exemplo n.º 6
0
    def for_user_and_view(cls, p4, p4user, view_name):
        """Factory to fetch user's permissions on a view."""
        LOG.debug("for_user_and_view() {u} {v}".format(u=p4user, v=view_name))

        group_list = p4.run('groups', '-i', p4user)
        group_dict = {group['group']:group for group in group_list}
        LOG.debug("group_dict.keys()={}".format(group_dict.keys()))

        vp = ViewPerm()
        vp.p4user_name = p4user
        vp.view_name   = view_name

        vp.view_pull   = p4gf_const.P4GF_GROUP_VIEW_PULL.format(view=view_name) in group_dict
        vp.view_push   = p4gf_const.P4GF_GROUP_VIEW_PUSH.format(view=view_name) in group_dict
        vp.global_pull = p4gf_const.P4GF_GROUP_PULL                             in group_dict
        vp.global_push = p4gf_const.P4GF_GROUP_PUSH                             in group_dict

        value = p4gf_util.first_value_for_key(
                    p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT),
                    'value')
        if value == '0':
            value = DEFAULT_PERM
        vp.default_pull = value == PERM_PULL
        vp.default_push = value == PERM_PUSH
        LOG.debug("counter={}".format(value))

        LOG.debug(vp)
        return vp
Exemplo n.º 7
0
    def _toggle_filetype(self, p4path, isx):
        """Returns the new file type for the named file, switching the
        executable state based on the isx value.

        Args:
            p4path: Path of the file to modify.
            isx: True if currently executable.

        Returns:
            New type for the file; may be None.
        """
        p4type = None
        if isx:
            p4type = '+x'
        else:
            # To remove a previously assigned modifier, the whole filetype
            # must be specified.
            for tipe in ['headType', 'type']:
                # For a file that was executable, is being renamed (with
                # edits), and is no longer executable, we need to handle the
                # fact that it's not yet in Perforce and so does not have a
                # headType.
                try:
                    p4type = p4gf_util.first_value_for_key(
                        self.ctx.p4.run(['fstat', '-T' + tipe, p4path]), tipe)
                except P4.P4Exception:
                    pass
                if p4type:
                    p4type = p4gf_p4filetype.remove_mod(p4type, 'x')
        return p4type
Exemplo n.º 8
0
    def for_user_and_view(cls, p4, p4user, view_name, required_perm):
        """Factory to fetch user's permissions on a view."""
        LOG.debug("for_user_and_view() {u} {v} {r}".format(u=p4user,
                                                           v=view_name,
                                                           r=required_perm))

        group_list = p4.run('groups', '-i', p4user)
        group_dict = {group['group']: group for group in group_list}
        LOG.debug3("group_dict.keys()={}".format(group_dict.keys()))

        vp = ViewPerm()
        vp.p4user_name = p4user
        vp.view_name = view_name

        vp.view_pull = p4gf_const.P4GF_GROUP_VIEW_PULL.format(
            view=view_name) in group_dict
        vp.view_push = p4gf_const.P4GF_GROUP_VIEW_PUSH.format(
            view=view_name) in group_dict
        vp.global_pull = p4gf_const.P4GF_GROUP_PULL in group_dict
        vp.global_push = p4gf_const.P4GF_GROUP_PUSH in group_dict

        value = p4gf_util.first_value_for_key(
            p4.run('counter', '-u',
                   p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT), 'value')
        if value == '0':
            value = DEFAULT_PERM
        vp.default_pull = value == PERM_PULL
        vp.default_push = value == PERM_PUSH
        LOG.debug("counter={}".format(value))

        LOG.debug(vp)
        return vp
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 _toggle_filetype(self, p4path, isx):
        """Returns the new file type for the named file, switching the
        executable state based on the isx value.

        Args:
            p4path: Path of the file to modify.
            isx: True if currently executable.

        Returns:
            New type for the file; may be None.
        """
        p4type = None
        if isx:
            p4type = '+x'
        else:
            # To remove a previously assigned modifier, the whole filetype
            # must be specified.
            for tipe in ['headType', 'type']:
                # For a file that was executable, is being renamed (with
                # edits), and is no longer executable, we need to handle the
                # fact that it's not yet in Perforce and so does not have a
                # headType.
                try:
                    p4type = p4gf_util.first_value_for_key(
                                self.ctx.p4.run(['fstat', '-T' + tipe, p4path]),
                                tipe)
                except P4.P4Exception:
                    pass
                if p4type:
                    p4type = p4gf_p4filetype.remove_mod(p4type, 'x')
        return p4type
Exemplo n.º 11
0
def _upgrade_p4gf(p4):
    """Perform upgrade from earlier versions of P4GF. This should be invoked
    using _maybe_perform_init() to avoid race conditions across hosts.
    """
    # If updating from 12.2 to 13.1 we need to create global config file
    # (this does nothing if file already exists)
    c = p4gf_config.create_file_global(p4)
    if c:
        _info(_("Global config file '{}' created.")
              .format(p4gf_config.depot_path_global()))
    else:
        _info(_("Global config file '{}' already exists.")
              .format(p4gf_config.depot_path_global()))
    # Ensure the time zone name has been set, else default to something sensible.
    r = p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME)
    tzname = p4gf_util.first_value_for_key(r, 'value')
    if tzname == "0" or tzname is None:
        msg = _("Counter '{}' not set, using UTC as default."          \
                " Change this to your Perforce server's time zone.") \
              .format(p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME)
        LOG.warn(msg)
        sys.stderr.write(NTR('Git Fusion: {}\n').format(msg))
        tzname = None
    else:
        # Sanity check the time zone name.
        try:
            pytz.timezone(tzname)
        except pytz.exceptions.UnknownTimeZoneError:
            LOG.warn("Time zone name '{}' unrecognized, using UTC as default".format(tzname))
            tzname = None
    if tzname is None:
        p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME, 'UTC')
Exemplo n.º 12
0
 def __get_timezone_offset(self, timestamp):
     """
     Determine the time zone offset for the given timestamp, using the.
     time zone name set in the P4GF time zone counter. For example, with
     time zone 'US/Pacific' and timestamp 1371663968, the offset returned
     will be the string '-0700'.
     """
     try:
         ts = int(timestamp)
     except ValueError:
         LOG.error("__get_timezone_offset() given non-numeric input {}".format(timestamp))
     if self.__tzname is None:
         r = self.ctx.p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME)
         value = p4gf_util.first_value_for_key(r, 'value')
         if value == '0' or value is None:
             # Upgrade from an EA system, perhaps, in which the upgrade counters
             # have been set but the later changes where not applied during init.
             msg = _("Counter '{}' not set, using UTC as default."
                     " Change this to your Perforce server's time zone.") \
                   .format(p4gf_const.P4GF_COUNTER_TIME_ZONE_NAME)
             LOG.warn(msg)
             value = NTR('UTC')
         self.__tzname = value
     try:
         mytz = pytz.timezone(self.__tzname)
     except pytz.exceptions.UnknownTimeZoneError:
         LOG.warn("Time zone name '{}' unrecognized, using UTC as default".format(self.__tzname))
         mytz = pytz.utc
     LOG.debug("__get_timezone_offset({}) with {}".format(ts, mytz))
     dt = datetime.datetime.fromtimestamp(ts, tz=pytz.utc)
     ct = dt.astimezone(mytz)
     return ct.strftime('%z')
Exemplo 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
    gfuser_perms_set = False
    reviews_users_perms_set = False
    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 '{user}'. Not changing")
                         .format(user=p4gf_const.P4GF_USER))
    else:
        l = protect_lines
        l.append('admin user {user} * //...'.format(user=p4gf_const.P4GF_USER))
        gfuser_perms_set = True

    review_perm = 'review user git-fusion-reviews-* * //...'
    review_perm_user_mask = 'review user git-fusion-reviews-*'
    review_perm_exists = False
    for perm in protect_lines:
        if perm.startswith(review_perm_user_mask):
                        # 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"))
            review_perm_exists = True
            break

    if not review_perm_exists:
        if not l:
            l = protect_lines
        l.append(review_perm)
        reviews_users_perms_set = True

    if l:
        p4gf_p4spec.set_spec(p4, 'protect', values={KEY_PROTECTIONS: l})
        if gfuser_perms_set:
            Verbosity.report(
                Verbosity.INFO,
                _("Protect table modified. User '{user}' granted admin permission.")
                .format(user=p4gf_const.P4GF_USER))
        if reviews_users_perms_set:
            Verbosity.report(
                Verbosity.INFO,
                _("Protect table modified. git-fusion-reviews-* granted reviews permission."))
def get_last_change(p4):
    """Fetch the last change number with which we synced the keys to the
    SSH configuration file. Returns a positive number, or zero if no saved
    counter value.
    """
    counter = p4.run('counter', '-u', _get_counter_name())
    if counter:
        return int(p4gf_util.first_value_for_key(counter, 'value'))
    else:
        return 0
Exemplo n.º 15
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))
Exemplo n.º 16
0
def _prevent_access(p4):
    """
    Prevent further access to Git Fusion while deleting everything.
    Return the previous value of the counter so it can be restored later.
    """
    result = p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PREVENT_NEW_SESSIONS)
    old_value = None
    if result:
        old_value = p4gf_util.first_value_for_key(result, 'value')
    p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PREVENT_NEW_SESSIONS, 'true')
    return old_value
Exemplo n.º 17
0
    def get_heartbeat(self):
        '''
        Return the current heartbeat value, if any.

        Might provide clue to what holds the lock.
        '''
        result = self.__p4__.run('counter', '-u', self.heartbeat_counter_name())
        value = p4gf_util.first_value_for_key(result, 'value')
        if not value or value == '0':
            return None
        return value
Exemplo n.º 18
0
    def get_heartbeat(self):
        '''
        Return the current heartbeat value, if any.

        Might provide clue to what holds the lock.
        '''
        value = p4gf_util.first_value_for_key(
                    self.__p4__.run('counter', '-u', self.heartbeat_counter_name()),
                    'value')
        if not value or value == '0':
            return None
        return value
Exemplo n.º 19
0
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 get_keys_latest_change(p4):
    """Retrieve the most recent change made to the user keys in Perforce.
    Returns a postive number, or zero if no changes have been made to the
    keys (i.e. no keys have been added).
    """
    try:
        change = p4.run('changes', '-m', '1', KEYS_PATH)
        if change:
            return int(p4gf_util.first_value_for_key(change, 'change'))
        else:
            return 0
    except P4Exception:
        return 0
Exemplo n.º 21
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
Exemplo n.º 22
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
Exemplo n.º 23
0
def _prevent_access(p4):
    """
    Prevent further access to Git Fusion while deleting everything.
    Return the previous value of the counter so it can be restored later.
    """
    result = p4.run('counter', '-u',
                    p4gf_const.P4GF_COUNTER_PREVENT_NEW_SESSIONS)
    old_value = None
    if result:
        old_value = p4gf_util.first_value_for_key(result, 'value')
    p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PREVENT_NEW_SESSIONS,
           'true')
    return old_value
Exemplo n.º 24
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
Exemplo n.º 25
0
 def _clear_heartbeat(self):
     '''
     Clear the heartbeat counter associated with this lock.
     '''
     # Clearing the heartbeat means we start all over with heartbeat tracking.
     self.__heartbeat_time = None
     self.__heartbeat_content = None
     # Suppress P4 exceptions here.
     # Don't care if fail, only lock counter matters.
     with self.__p4__.at_exception_level(P4.RAISE_NONE):
         counter_name = self.heartbeat_counter_name()
         result = self.__p4__.run('counter', '-u', '-d', counter_name)
         if p4gf_util.first_value_for_key(result, 'counter'):
             LOG.getChild("heartbeat").debug("deleted counter {}".format(counter_name))
Exemplo n.º 26
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
Exemplo n.º 27
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
    def get_branch_dict(self):
        """Get a branch dictionary for this repo.

        If the p4gf_config exists, use that.
        Else if the p4 client exists
        create a branch dict containing a branch from the client views.
        Else return None
        """
        LOG.debug("get_branch_dict for {0}".format(self.view_name))
        # Repo config file already checked into Perforce?
        # Use that.
        config_path = p4gf_config.depot_path_repo(self.view_name)
        config_exists = p4gf_util.depot_file_exists(self.p4, config_path)
        if config_exists:
            self.config = p4gf_config.get_repo(self.p4, self.view_name)
            if self.config:
                return p4gf_branch.dict_from_config(self.config, self.p4)
            else:
                return None
        else:
            LOG.debug("checking if client {0} exists.".format(self.view_name))
            if not p4gf_util.spec_exists(self.p4, 'client', self.view_name):
                LOG.debug("         client {0} NOT exists.".format(
                    self.view_name))
                return None
            view_lines = p4gf_util.first_value_for_key(
                self.p4.run('client', '-o', '-t', self.view_name,
                            self.p4client), 'View')
            if not view_lines:
                return None
            else:
                # create a Branch object to manage this client view
                if isinstance(view_lines, str):
                    view_lines = view_lines.splitlines()
                LOG.debug(
                    "create branch from client views: {0}".format(view_lines))
                branch = p4gf_branch.Branch()
                branch.branch_id = 'master'
                branch.git_branch_name = 'master'
                branch.view_p4map = P4.Map(view_lines)
                branch.view_lines = view_lines
                LOG.debug(
                    "create branch from client branch view_p4map: {0}".format(
                        branch.view_p4map))
                LOG.debug(
                    "create branch from client branch view_lines: {0}".format(
                        branch.view_lines))
                branch_dict = {}
                branch_dict[branch.branch_id] = branch
                return branch_dict
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')
        report(DEBUG, 'p4 protect:\n{}'.format(r))
    if p4.errors:
        report(ERROR, "Unable to run 'p4 protect -o'.")
        for e in p4.errors:
            report(ERROR, e)
        exit(2)

    protections = p4gf_util.first_value_for_key(r, KEY_PROTECTIONS)
    return protections
Exemplo n.º 30
0
    def canceled(self):
        '''
        Has our lock counter been cleared?

        This is one way to remote-kill a long-running Git Fusion task.
        '''
        value = p4gf_util.first_value_for_key(
            self.__p4__.run('counter', '-u', self.counter_name()), 'value')

        if value != "0":  # Compare as strings, "0" != int(0)
            return False

        LOG.error("Lock canceled: {name}={value}".format(
            name=self.counter_name(), value=value))
        return True
Exemplo n.º 31
0
def create_default_perm(p4, perm=DEFAULT_PERM):
    """Create the 'stick all users into this pull/push permission group'
    default counter. If counter already exists with non-zero value,
    leave it unchanged.
    """
    counter = p4gf_util.first_value_for_key(
        p4.run('counter', '-u',
               p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT), 'value')
    if counter != None and counter != '0':
        # Somebody already set it.
        return False

    p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT,
           perm)
    return True
Exemplo n.º 32
0
 def _acquire_attempt(self):
     """Attempt an atomic increment. If the result is 1, then we now
     own the lock. Any other value means somebody else owns the
     lock.
     """
     value = p4gf_util.first_value_for_key(
             self.__p4__.run('counter', '-u', '-i', self.counter_name()),
             'value')
     acquired = value == "1"  # Compare as strings, "1" != int(1)
     LOG.debug("_acquire_attempt {name} pid={pid} acquired={a} value={value}"
               .format(pid=os.getpid(),
                       a=acquired,
                       name=self.counter_name(),
                       value=value))
     return acquired
Exemplo n.º 33
0
 def _acquire_attempt(self):
     """Attempt an atomic increment. If the result is 1, then we now
     own the lock. Any other value means somebody else owns the
     lock.
     """
     value = p4gf_util.first_value_for_key(
             self.__p4__.run('counter', '-u', '-i', self.counter_name()),
             'value')
     acquired = value == "1"  # Compare as strings, "1" != int(1)
     LOG.debug("_acquire_attempt {name} pid={pid} acquired={a} value={value}"
               .format(pid=os.getpid(),
                       a=acquired,
                       name=self.counter_name(),
                       value=value))
     return acquired
Exemplo n.º 34
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
Exemplo n.º 35
0
    def canceled(self):
        '''
        Has our lock counter been cleared?

        This is one way to remote-kill a long-running Git Fusion task.
        '''
        value = p4gf_util.first_value_for_key(
                        self.__p4__.run('counter', '-u', self.counter_name()),
                        'value')

        if value != "0":  # Compare as strings, "0" != int(0)
            return False

        LOG.error("Lock canceled: {name}={value}"
                  .format(name=self.counter_name(), value=value))
        return True
Exemplo n.º 36
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
Exemplo n.º 37
0
def create_default_perm(p4, perm=DEFAULT_PERM):
    """Create the 'stick all users into this pull/push permission group'
    default counter. If counter already exists with non-zero value,
    leave it unchanged.
    """
    counter = p4gf_util.first_value_for_key(
                p4.run('counter', '-u', p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT),
                'value')
    if counter != None and counter != '0':
        # Somebody already set it.
        return False

    p4.run('counter', '-u',
           p4gf_const.P4GF_COUNTER_PERMISSION_GROUP_DEFAULT,
           perm)
    return True
Exemplo n.º 38
0
    def get_branch_dict(self):
        """Get a branch dictionary for this repo.

        If the p4gf_config exists, use that.
        Else if the p4 client exists
        create a branch dict containing a branch from the client views.
        Else return None
        """
        LOG.debug("get_branch_dict for {0}".format(self.view_name))
        # Repo config file already checked into Perforce?
        # Use that.
        config_path   = p4gf_config.depot_path_repo(self.view_name)
        config_exists = p4gf_util.depot_file_exists(self.p4, config_path)
        if config_exists:
            self.config = p4gf_config.get_repo(self.p4, self.view_name)
            if self.config:
                return p4gf_branch.dict_from_config(self.config, self.p4)
            else:
                return None
        else:
            LOG.debug("checking if client {0} exists.".format(self.view_name))
            if not p4gf_util.spec_exists(self.p4, 'client', self.view_name):
                LOG.debug("         client {0} NOT exists.".format(self.view_name))
                return None
            view_lines = p4gf_util.first_value_for_key(
                    self.p4.run('client', '-o', '-t', self.view_name, self.p4client),
                    'View')
            if not view_lines:
                return None
            else:
                # create a Branch object to manage this client view
                if isinstance(view_lines, str):
                    view_lines = view_lines.splitlines()
                LOG.debug("create branch from client views: {0}".format(view_lines))
                branch = p4gf_branch.Branch()
                branch.branch_id = 'master'
                branch.git_branch_name = 'master'
                branch.view_p4map = P4.Map(view_lines)
                branch.view_lines = view_lines
                LOG.debug("create branch from client branch view_p4map: {0}".
                        format(branch.view_p4map))
                LOG.debug("create branch from client branch view_lines: {0}".
                        format(branch.view_lines))
                branch_dict = {}
                branch_dict[branch.branch_id] = branch
                return branch_dict
def ensure_protects_configurable():
    """Grant 'p4 protects -u' permission to admin users."""

    if not p4gf_version.p4d_version_supports_admin_user(p4):
        return

    v = p4gf_util.first_value_for_key(
        p4.run('configure', 'show', CONFIGURABLE_ALLOW_ADMIN), KEY_VALUE)
    if v == '1':
        report(
            INFO, 'Configurable {} already set to 1. Not setting.'.format(
                CONFIGURABLE_ALLOW_ADMIN))
        return False

    p4.run('configure', 'set', '{}=1'.format(CONFIGURABLE_ALLOW_ADMIN))
    report(INFO, 'Configurable {} set to 1.'.format(CONFIGURABLE_ALLOW_ADMIN))
    return True
def ensure_protects_configurable():
    """Grant 'p4 protects -u' permission to admin users."""

    if not p4gf_version.p4d_version_supports_admin_user(p4):
        return

    v = p4gf_util.first_value_for_key(
            p4.run('configure', 'show', CONFIGURABLE_ALLOW_ADMIN),
            KEY_VALUE)
    if v == '1':
        report(INFO, 'Configurable {} already set to 1. Not setting.'
                     .format(CONFIGURABLE_ALLOW_ADMIN))
        return False

    p4.run('configure', 'set', '{}=1'.format(CONFIGURABLE_ALLOW_ADMIN))
    report(INFO, 'Configurable {} set to 1.'
                 .format(CONFIGURABLE_ALLOW_ADMIN))
    return True
Exemplo n.º 41
0
 def acquire(self):
     """Attempt to acquire a shared lock.
     """
     counter_name = host_view_lock_name(self.__host_name, self.__view_name)
     counter_lock = CounterLock(self.__p4, counter_name, self.__timeout_secs)
     shared_name = shared_host_view_name(self.__host_name, self.__view_name)
     start_time = time.time()
     while not self.__has:
         with counter_lock:
             # Get the current value for the shared lock.
             current = p4gf_util.first_value_for_key(
                     self.__p4.run('counter', '-u', shared_name), 'value')
             if current and current[0] == '*':
                 # Exclusive lock in place, check if process still alive
                 (pid, args) = current.split('\t', 1)
                 pid = pid.strip('*')
                 if not check_process_alive(pid, args):
                     # Seems the lock holder has died
                     try:
                         self.__p4.run('counter', '-u', '-d', shared_name)
                     except P4Exception:
                         LOG.warn("lock counter deletion failed: {}".format(shared_name))
                     continue
             if current is None or current == '0' or current[0] != '*':
                 # Add our PID to the list of shared lock holders.
                 value = self._lock_value()
                 if current and current != '0':
                     value = current + '\n' + value
                 self.__p4.run('counter', '-u', shared_name, value)
                 self.__has = True
                 # If current was empty, then we're the first acquisition.
                 if      (current is None or current == '0') \
                     and  self.__first_acquire_func:
                     self.__first_acquire_func()
         if not self.__has:
             elapsed = time.time() - start_time
             if self.__timeout_secs and self.__timeout_secs <= elapsed:
                 msg = _('Unable to acquire lock: {}').format(shared_name)
                 if current:
                     msg += _('\nLock holder: {}').format(current)
                 raise RuntimeError(msg)
             # Having released the lock and not acquired the shared lock,
             # pause briefly before trying again.
             time.sleep(_RETRY_PERIOD)
Exemplo n.º 42
0
 def acquire(self):
     """Attempt to acquire a shared lock.
     """
     counter_name = host_view_lock_name(self.__host_name, self.__view_name)
     counter_lock = CounterLock(self.__p4, counter_name, self.__timeout_secs)
     shared_name = shared_host_view_name(self.__host_name, self.__view_name)
     start_time = time.time()
     while not self.__has:
         with counter_lock:
             # Get the current value for the lock.
             current = p4gf_util.first_value_for_key(
                     self.__p4.run('counter', '-u', shared_name), 'value')
             if current is None or current == '0':
                 # Set the value to our PID wrapped in asterisks to signal
                 # that it is an exclusive lock.
                 value = self._lock_value()
                 self.__p4.run('counter', '-u', shared_name, value)
                 self.__has = True
             else:
                 # Shared locks in place, check if processes still alive
                 okay_to_steal = True
                 for row in current.splitlines():
                     (pid, args) = row.split('\t', 1)
                     if check_process_alive(pid, args):
                         okay_to_steal = False
                         break
                 if okay_to_steal:
                     # Seems the lock holders have all died
                     try:
                         self.__p4.run('counter', '-u', '-d', shared_name)
                     except P4Exception:
                         LOG.warn("lock counter deletion failed: {}".format(shared_name))
                     continue
         if not self.__has:
             elapsed = time.time() - start_time
             if self.__timeout_secs and self.__timeout_secs <= elapsed:
                 msg = _('Unable to acquire lock: {}').format(shared_name)
                 if current:
                     msg += _('\nLock holder: {}').format(current)
                 raise RuntimeError(msg)
             # Having released the lock and not acquired the shared lock,
             # pause briefly before trying again.
             time.sleep(_RETRY_PERIOD)
Exemplo n.º 43
0
 def release(self):
     """Release a previously acquired hold on the shared lock. Does nothing
     if the lock is not currently held by this instance.
     """
     if not self.__has:
         return
     counter_name = host_view_lock_name(self.__host_name, self.__view_name)
     shared_name = shared_host_view_name(self.__host_name, self.__view_name)
     with CounterLock(self.__p4, counter_name):
         current = p4gf_util.first_value_for_key(
             self.__p4.run('counter', '-u', shared_name), 'value')
         expected = self._lock_value()
         if current == expected:
             # Delete the exclusive lock
             try:
                 self.__p4.run('counter', '-u', '-d', shared_name)
             except P4Exception:
                 LOG.warn("lock counter deletion failed: {}".format(shared_name))
         else:
             LOG.warn("Lock {0} does not belong to us, not releasing".format(shared_name))
     self.__has = False
Exemplo n.º 44
0
def get_shared_host_view_lock_state(p4, host_name, view_name):
    '''Does any process already hold this shared host+view lock?

    Returns
        None        if none do
        EXCLUSIVE   if one process holds an exclusive lock
        SHARED      if one or more processes hold shared locks

    Returns None if there is a stale lock suitable for stealing,
    but does not actually steal the lock.
    '''
    shared_name = shared_host_view_name(host_name, view_name)
    # Get the current value for the shared lock.
    current = p4gf_util.first_value_for_key(
            p4.run('counter', '-u', shared_name), 'value')
    if (not current) or (current == '0'):
        return None

    if current[0] == '*':
        # Exclusive lock in place, check if process still alive.
        (pid, args) = current.split('\t', 1)
        pid = pid.strip('*')
        if not check_process_alive(pid, args):
            # Seems the lock holder has died.
            return None
        else:
            return EXCLUSIVE

    # Shared lock(s) in place, check if process(es) still alive.
    okay_to_steal = True
    for row in current.splitlines():
        (pid, args) = row.split('\t', 1)
        if check_process_alive(pid, args):
            okay_to_steal = False
            break
    if okay_to_steal:
        # Seems the lock holders have all died.
        return None
    return SHARED
Exemplo n.º 45
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))
Exemplo n.º 46
0
def repo_from_template_client(p4, view_name, view_name_p4client, client_name,
                              client_root, enable_mismatched_rhs):
    '''
    Create a new Perforce client spec <client_name> using existing Perforce
    client spec <view_name> as a template (just use its View).
    '''
    # view_name_p4client is the p4client
    # view_name        is the gfinternal repo name
    # view_name differs from view_name_p4client if latter contains special chars
    #           or was configured with --p4client argument

    if not p4gf_util.spec_exists(p4, 'client', view_name_p4client):
        return INIT_REPO_NOVIEW

    client = p4.run('client', '-o', view_name_p4client)[0]
    if 'Stream' in client:
        return _repo_from_stream(p4, view_name, client.get('Stream'),
                                 client_name, client_root,
                                 enable_mismatched_rhs)

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

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

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

    create_repo_client(p4, view_name, client_name, client_root, view, None)
    return INIT_REPO_OK
Exemplo n.º 47
0
 def get_timezone(self):
     """get server's timezone via p4 info"""
     server_date = p4gf_util.first_value_for_key(self.p4.run("info"), 'serverDate')
     self.timezone = server_date.split(" ")[2]
Exemplo n.º 48
0
 def get_timezone_serverversion(self):
     """get server's timezone and server version via p4 info"""
     r = self.p4.run_info()
     server_date = p4gf_util.first_value_for_key(r, 'serverDate')
     self.timezone = server_date.split(" ")[2]
     self.server_version = p4gf_util.first_value_for_key(r, 'serverVersion')