コード例 #1
0
def main():
    """Parse the command-line arguments and report on locks."""
    desc = _(DESCRIPTION)
    parser = p4gf_util.create_arg_parser(desc=desc)
    parser.add_argument(
        NTR('--config'),
        metavar=NTR('config'),
        help=_('Path to Git Fusion p4gf_config file (required)'),
        required=True)
    parser.add_argument('-u',
                        '--p4user',
                        metavar='p4user',
                        help=_('Perforce user'))
    parser.add_argument('-p',
                        '--p4port',
                        metavar='p4port',
                        help=_('Perforce server'))
    parser.add_argument('--locale',
                        metavar='locale',
                        default='en_US.UTF-8',
                        help=_('system locale setting'))
    args = parser.parse_args()

    need_serverid = False
    try:
        p4gf_util.get_server_id()
    except:  # pylint: disable=W0702
        need_serverid = True

    # If connect args not passed, check that the environment is set.
    if not args.p4port:
        if 'P4PORT' not in os.environ and 'P4GF_ENV' not in os.environ:
            print(
                _("Neither --p4port is an argument nor are P4GF_ENV and P4PORT in the environment."
                  ))
            sys.exit(0)
        if 'P4PORT' in os.environ:
            args.p4port = os.environ['P4PORT']
    else:
        # Set the requested port for Git Fusion's environment
        os.environ['P4PORT'] = args.p4port

    if not args.p4user:
        if 'P4USER' not in os.environ:
            print(
                _("Neither --p4user is an argument nor is P4USER in the environment."
                  ))
            sys.exit(0)
        else:
            args.p4user = os.environ['P4USER']
    else:
        # Set the requested user for Git Fusion's environment
        os.environ['P4USER'] = args.p4user

    repo_size = RepoSize(args.config, args.p4port, args.p4user, args.locale,
                         need_serverid)
    repo_size.estimate_size()
    repo_size.report()
コード例 #2
0
def create_p4_temp_client(port=None, user=None, skip_count=False):
    """Create a connected P4 instance with a generic temporary client.

    Dropping the connection will automatically delete the client. This is
    useful for owning the locks and permitting reliable lock stealing by
    other processes.

    :return: P4API instance.

    """
    p4 = create_p4(port, user, warn_no_client=False)
    if p4 is None:
        # Propagate the error (that has already been reported).
        return None
    name = p4gf_const.P4GF_OBJECT_CLIENT_UNIQUE.format(
        server_id=p4gf_util.get_server_id(), uuid=str(uuid.uuid1()))
    client = p4.fetch_client(name)
    client['Owner'] = p4gf_const.P4GF_USER
    client['LineEnd'] = NTR('unix')
    client['View'] = [
        '//{0}/... //{1}/...'.format(p4gf_const.P4GF_DEPOT, name)
    ]
    # to prevent the mirrored git commit/tree objects from being retained in the
    # git-fusion workspace, set client option 'rmdir' and sync #none in p4gf_gitmirror
    client['Options'] = p4gf_const.CLIENT_OPTIONS.replace("normdir", "rmdir")
    client['Root'] = p4gf_const.P4GF_HOME
    # The -x option is a deep undoc feature that signals to p4d that this
    # is a temporary client, which will be automatically deleted upon
    # disconnect. Requires passing the client specification using -i flag.
    # N.B. this client cannot shelve changes. See @465851 for details.
    # N.B. only one temporary client per connection will be auto-deleted
    p4.client = name
    p4.save_client(client, '-x')
    LOG.debug("create_p4_temp_client() created temp client %s", name)
    if 'P4T4TEST_ORIG_LANG' in os.environ and not skip_count:
        # In the testing environment, we check that each process created no
        # more than one temporary client (concurrently). Keep the highest
        # value, rather than whatever the last count happened to be.
        prefix = p4gf_const.P4GF_OBJECT_CLIENT_UNIQUE.format(
            server_id=p4gf_util.get_server_id(), uuid='')
        count = _count_active(prefix)
        # Some tests set up an unnatural environment, so don't let those
        # blow up in unexpected ways (i.e. fail gracefully elsewhere).
        with p4.at_exception_level(P4.P4.RAISE_NONE):
            value = p4gf_p4key.get(
                p4, "git-fusion-temp-clients-{}".format(os.getpid()))
            if int(value) < count:
                p4gf_p4key.set(
                    p4, "git-fusion-temp-clients-{}".format(os.getpid()),
                    str(count))
    return p4
コード例 #3
0
def _last_copied_tag_counter_name(ctx):
    '''
    Return the name of a counter that holds the latest tag changelist
    number for this Git Fusion server.
    '''
    return _calc_last_copied_tag_counter_name(ctx.config.view_name,
                                              p4gf_util.get_server_id())
コード例 #4
0
    def heartbeat_content(self):
        '''
        What should we write to our heartbeat counter?
        Enough data that an admin could figure out who's hogging the lock.

        If enough time has elapsed since the last call to this function,
        updates the content string.

        Returns a tuple containing the current and previous content strings.
        '''
        now = time.time()
        if self.__heartbeat_time and now - self.__heartbeat_time < HEART_RATE:
            return self.__heartbeat_content, self.__heartbeat_content

        self.__heartbeat_time = now

        # Produce a heartbeat value that is unique for each host and
        # process, and changes each time it is updated. Values are not so
        # important, but the value must continue to change so that others
        # can determine if the lock holder has died.
        val = NTR('{host} -- {process} -- {time}') \
              .format( host     = p4gf_util.get_server_id()
                     , process  = os.getpid()
                     , time     = int(self.__heartbeat_time)
                     )
        last = self.__heartbeat_content
        self.__heartbeat_content = val
        return self.__heartbeat_content, last
コード例 #5
0
def shared_host_view_lock_exists(p4, view_name):
    '''
    Are one or more processes already cloning through this repo?
    '''
    host_name = p4gf_util.get_server_id()
    result = get_shared_host_view_lock_state(p4, host_name, view_name)
    return result == SHARED
コード例 #6
0
 def last_copied_change_counter_name(self):
     '''
     Return a counter that holds the highest changelist number
     copied to the our repo, on our Git Fusion server.
     '''
     return calc_last_copied_change_counter_name(self.config.view_name,
                                                 p4gf_util.get_server_id())
コード例 #7
0
 def last_copied_change_counter_name(self):
     '''
     Return a counter that holds the highest changelist number
     copied to the our repo, on our Git Fusion server.
     '''
     return calc_last_copied_change_counter_name(
                   self.config.view_name
                 , p4gf_util.get_server_id())
コード例 #8
0
 def _generate_client_name(self):
     '''
     Return "git-fusion-{server_id}-{repo_name}-temp-{n}", suitable for use as a
     name for a temporary client
     '''
     return p4gf_const.P4GF_REPO_TEMP_CLIENT.format(
         server_id=p4gf_util.get_server_id(),
         repo_name=self.ctx.config.view_name,
         n=len(self.q.q))
コード例 #9
0
def shared_host_view_lock(p4, view_name
                         , first_acquire_func=None
                         , last_release_func=None):
    '''Return a shared lock for the desired view, specific to the current host.
    '''
    host_name = p4gf_util.get_server_id()
    return SharedViewLock(p4, host_name, view_name
                          , first_acquire_func=first_acquire_func
                          , last_release_func=last_release_func)
コード例 #10
0
def _get_counter_name():
    """Generate the name of the counter for keeping track of the last change
    that this server has retrieved for the user keys.
    """
    global CounterName
    if not CounterName:
        host = p4gf_util.get_server_id()
        CounterName = p4gf_const.P4GF_COUNTER_UPDATE_AUTH_KEYS.format(host)
    return CounterName
コード例 #11
0
def _get_p4key_name():
    """Generate the name of the p4key for keeping track of the last change
    that this server has retrieved for the user keys.
    """
    global P4KeyName
    if not P4KeyName:
        host = p4gf_util.get_server_id()
        P4KeyName = p4gf_const.P4GF_P4KEY_UPDATE_AUTH_KEYS.format(host)
    return P4KeyName
コード例 #12
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', _('*****@*****.**'))
コード例 #13
0
 def __init__(self, p4, blocking=True):
     """Init lock, setting lock key name used for reviews."""
     super(ReviewsLock, self).__init__(
         p4=p4,
         lock_key=p4gf_const.P4GF_REVIEWS_COMMON_LOCK,
         blocking=blocking)
     self.content = {
         'server_id': p4gf_util.get_server_id(),
         'process_id': os.getpid(),
         'start_time': _process_start_time()
     }
コード例 #14
0
def _remove_local_root(localroot):
    """
    Remove the contents of the P4GF local workspace, disregarding whether
    the root is a symbolic link.
    Save and re-write the server-id file after removing contents.
    """
    LOG.debug2("_remove_local_root(): {}".format(localroot))
    # get the server_id
    server_id = p4gf_util.get_server_id()
    _remove_tree(localroot)
    # re-write server_id
    p4gf_util.write_server_id_to_file(server_id)
コード例 #15
0
def _remove_local_root(localroot):
    """
    Remove the contents of the P4GF local workspace, disregarding whether
    the root is a symbolic link.
    Save and re-write the server-id file after removing contents.
    """
    LOG.debug2("_remove_local_root(): {}".format(localroot))
    # get the server_id
    server_id = p4gf_util.get_server_id()
    _remove_tree(localroot)
    # re-write server_id
    p4gf_util.write_server_id_to_file(server_id)
コード例 #16
0
def init(p4):
    """Ensure both global and host-specific initialization are completed."""
    _check_for_old_p4key(p4)

    started_p4key = p4gf_const.P4GF_P4KEY_INIT_STARTED
    complete_p4key = p4gf_const.P4GF_P4KEY_INIT_COMPLETE
    _init_if_needed(p4, started_p4key, complete_p4key, _global_init,
                    _('Permissions already initialized. Not changing.'))

    server_id = p4gf_util.get_server_id()
    started_p4key = p4gf_const.P4GF_P4KEY_INIT_STARTED + '-' + server_id
    complete_p4key = p4gf_const.P4GF_P4KEY_INIT_COMPLETE + '-' + server_id
    p4gf_dir = p4gf_const.P4GF_HOME

    def client_init(p4):
        """Perform host-specific initialization (and create sample usermap)."""
        # Set up the host-specific client.
        _create_client(p4)
        # Ensure the default user map and global config files are in place.
        _create_user_map(p4, p4.client, p4gf_dir)
        p4gf_config.GlobalConfig.init(p4)
        with p4.at_exception_level(p4.RAISE_ERROR):
            p4gf_config.GlobalConfig.write_if(p4)
        _delete_old_init_p4keys(p4, server_id)

    if not _init_if_needed(p4, started_p4key, complete_p4key, client_init,
                           _('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=p4.client)]
        p4gf_p4spec.ensure_spec_values(p4, 'client', p4.client,
                                     {'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_p4key = p4gf_const.P4GF_P4KEY_UPGRADE_STARTED
    complete_p4key = p4gf_const.P4GF_P4KEY_UPGRADE_COMPLETE
    _init_if_needed(p4, started_p4key, complete_p4key, _upgrade_p4gf,
                    _('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', _('*****@*****.**'))

    # Turn on CVE-CVE-2014-9390 rejection added in Git 2.2.1.
    # This linux server isn't vulnerable, but we still don't want to host
    # offending repos that could hit Windows/Mac OS X workstations.
    _ensure_git_config_non_empty('receive.fsckObjects', True)
    _ensure_git_config_non_empty('core.protectHFS',     True)
    _ensure_git_config_non_empty('core.protectNTFS',    True)
コード例 #17
0
    def __init__(self, p4, repo_name, blocking=True, group_id=None):
        """Initialize the lock."""
        super(RepoLock, self).__init__(p4, blocking)
        self.lock_key = p4gf_const.P4GF_P4KEY_LOCK_VIEW.format(repo_name=repo_name)
        self.owners_key = p4gf_const.P4GF_P4KEY_LOCK_VIEW_OWNERS.format(repo_name=repo_name)
        self.lock = SimpleLock(p4, self.lock_key, blocking=blocking)

        self.group_id = group_id or str(os.getpid())
        self.server_id = p4gf_util.get_server_id()
        self.process_id = os.getpid()
        self.start_time = _process_start_time()
        self.ignore_pending_acquire = False
        self._post_lock_release_cb = None
        self._transfer_complete_cb = None
        self._acquire_time = None
        self._repo_name = repo_name
コード例 #18
0
 def unlock_delete_temp_clients(self):
     """Unlock the temp clients so the user may consequently delete them."""
     pattern = p4gf_const.P4GF_REPO_TEMP_CLIENT.format(
         server_id=p4gf_util.get_server_id(),
         repo_name=self.ctx.config.repo_name,
         uuid='*')
     clients = [
         client['client']
         for client in self.ctx.p4gfrun('clients', '-e', pattern)
     ]
     options = re.sub('locked', 'unlocked', p4gf_const.CLIENT_OPTIONS)
     for client in clients:
         p4gf_p4spec.ensure_spec_values(self.ctx.p4gf,
                                        spec_type='client',
                                        spec_id=client,
                                        values={'Options': options})
         self.ctx.p4gfrun('client', '-d', client)
コード例 #19
0
    def cleanup_all(self):
        """Find and delete all temporary clients for the associated repo.

        Assumes the caller has the lock on the repository.

        """
        LOG.debug2("cleanup_all() removing all temp clients...")
        pattern = p4gf_const.P4GF_REPO_TEMP_CLIENT.format(
            server_id=p4gf_util.get_server_id(),
            repo_name=self.ctx.config.repo_name,
            uuid='*')
        clients = self.ctx.p4gfrun('clients', '-e', pattern)
        for client in clients:
            client_name = client['client']
            self.ctx.p4gfrun('client', '-d', '-f', client_name)
            LOG.debug("removing temp client {0}".format(client_name))
        LOG.debug2("cleanup_all() removed %s temp clients", len(clients))
コード例 #20
0
def overwrite_last_copied_tag(p4, repo_name, change_num):
    """Set the changelist number for the most recent tags change.

    :type p4: :class:`P4API`
    :param p4: P4 API instance

    :type repo_name: str
    :param repo_name: name fo the Git Fusion repository

    :type change_num: int || str
    :param change_num: changelist number to assign to tags key.

    """
    keyname = _calc_last_copied_tag_p4key_name(repo_name,
                                               p4gf_util.get_server_id())
    LOG.debug('overwrite_last_copied_tag() assigning {} to {}'.format(
        change_num, keyname))
    return P4Key.set(p4, keyname, change_num)
コード例 #21
0
ファイル: p4gf_init.py プロジェクト: spearhead-ea/git-fusion
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 cleanup(self):
        '''
        Delete any temp client specs created on this server for this repo.

        Don't limit this to clients created by this pool instance.
        '''
        pattern = p4gf_const.P4GF_REPO_TEMP_CLIENT.format(
            server_id=p4gf_util.get_server_id(),
            repo_name=self.ctx.config.view_name,
            n='*')
        clients = [
            client['client']
            for client in self.ctx.p4gfrun(NTR(["clients", "-e", pattern]))
        ]
        for client in clients:
            self.ctx.p4gfrun(NTR(["client", "-d", client]))
        # also clear this instance of references to deleted clients
        self.q.clear()
        self.view_lines_to_client_name.clear()
コード例 #23
0
    def _create_client_name_root_desc(self):
        """Return a tuple of (temp client name, root dir, description).

        Used to create temp clients.

        Name is of the form: "git-fusion-{server_id}-{repo_name}-temp-{uuid}".
        Ensure root dir exists.
        """
        desc = (_("Created by Perforce Git Fusion for queries in '{view}'.").
                format(view=self.ctx.config.repo_name))
        n = len(self.clients) + 1
        # There is a slight chance we could collide here with other
        # processes operating within the same root directory. But, as long
        # as that work is happening within the p4key lock, we should be
        # okay. We are mostly concerned with having unique client names.
        client_root = "{}-temp-{}/".format(self.ctx.repo_dirs.p4root, n)
        if not os.path.exists(client_root):
            os.makedirs(client_root)
        client_name = p4gf_const.P4GF_REPO_TEMP_CLIENT.format(
            server_id=p4gf_util.get_server_id(),
            repo_name=self.ctx.config.repo_name,
            uuid=uuid.uuid1())
        return (client_name, client_root, desc)
コード例 #24
0
def remove_old_temp_and_repo_clients(p4):
    """Remove the old style temp clients and repo clients."""

    server_id = p4gf_util.get_server_id()

    # Get a list of old style temp repo clients which may still exist.
    template = "git-fusion-{server_id}-{repo_name}-temp-{n}"
    pattern = template.format( server_id=server_id,
                               repo_name='*',
                               n='*')
    clients = [client['client'] for client
               in p4.run(NTR(["clients", "-e", pattern]))]

    for client in clients:
        try:
            p4.run(NTR(["client", "-d", "-f", client]))
            print(_("removed temp client {client}").format(client=client))
        except P4.P4Exception:
            print(_("cannot remove temp client {client}").format(client=client))

    # Get a list of old style permanent repo clients.
    old_client_repo_re = "git-fusion-{0}-[^-]+$".format(server_id)
    old_client_repo_re = re.compile(old_client_repo_re)
    pattern = p4gf_const.P4GF_REPO_CLIENT.format( server_id=server_id,
                               repo_name='*')
    clients = []
    for client in [client['client'] for client in p4.run(NTR(["clients", "-e", pattern]))]:
        if old_client_repo_re.match(client):
            clients.append(client)

    for client in clients:
        try:
            p4.run(NTR(["client", "-d", "-f", client]))
            print(_("removed temp client {client}").format(client=client))
        except P4.P4Exception:
            print(_("cannot remove temp client {client}").format(client=client))
コード例 #25
0
 def _set_server_repo_config_rev(self, value):
     """Get the config file rev for the repo from the p4key."""
     assert value is not None
     key = p4gf_const.P4GF_P4KEY_REPO_SERVER_CONFIG_REV.format(
         repo_name=self.repo_name, server_id=p4gf_util.get_server_id())
     p4gf_util.set_p4key(self.p4, key, value)
コード例 #26
0
def _last_copied_tag_p4key_name(ctx):
    """Return the name of a p4key that holds the latest tag changelist
    number for this Git Fusion server.
    """
    return _calc_last_copied_tag_p4key_name(ctx.config.repo_name,
                                            p4gf_util.get_server_id())
コード例 #27
0
def main():
    """Parse the command-line arguments and report on locks."""
    # pylint: disable=too-many-statements
    desc = _("Report the currently held locks in Git Fusion.")
    parser = p4gf_util.create_arg_parser(desc=desc)
    parser.add_argument('--test',
                        action='store_true',
                        help=_('invoke test mode, acquire locks and report'))
    parser.add_argument(
        '--test2',
        action='store_true',
        help=_(
            'invoke test mode, acquire locks and report, set dead processes.'))
    args = parser.parse_args()

    p4gf_util.has_server_id_or_exit()
    server_id = p4gf_util.get_server_id()
    p4 = p4gf_create_p4.create_p4_temp_client()
    if not p4:
        sys.exit(1)
    print("Connecting to P4PORT={} as P4USER={}".format(p4.port, p4.user))
    if args.test or args.test2:
        repo_name = "p4gf_test_status_repo"
        status_key_name = p4gf_p4key.calc_repo_status_p4key_name(
            repo_name, None)
        p4gf_p4key.set(p4, status_key_name, 'Push 1 completed successfully')
        pushid_key_name = p4gf_p4key.calc_repo_push_id_p4key_name(repo_name)
        p4gf_p4key.set(p4, pushid_key_name, '1')
        # create a process and kill it and set its dead pid as a RepoLock owner below.

        if args.test:
            # A test with nothing stale
            with ExitStack() as stack:
                stack.enter_context(p4gf_lock.ReviewsLock(p4))
                stack.enter_context(p4gf_lock.RepoLock(p4, repo_name))
                stack.enter_context(p4gf_git_repo_lock.read_lock(repo_name))
                stack.enter_context(
                    p4gf_git_repo_lock.write_lock(repo_name, upgrade=True))
                print_lock_status(p4, server_id)

        else:  # if args.test2
            # Now a test with some DEAD processes and a stale view Lock
            dead_process = subprocess.Popen(['echo', 'x'],
                                            stdout=subprocess.DEVNULL)
            dead_process.kill()
            while dead_process.returncode is None:
                dead_process.communicate()
            lock2 = None
            with ExitStack() as stack:
                stack.enter_context(p4gf_lock.ReviewsLock(p4))
                # first lock owner
                lock1 = p4gf_lock.RepoLock(p4, repo_name)
                # second lock owner with same group_id and a dead pid
                lock2 = p4gf_lock.RepoLock(p4,
                                           repo_name,
                                           group_id=lock1.group_id)
                lock2.process_id = dead_process.pid
                # acquire the first RepoLock
                stack.enter_context(lock1)
                # Use low level method to add this DEAD pid to the group's lock owners
                lock2.do_acquire()
                stack.enter_context(p4gf_git_repo_lock.read_lock(repo_name))
                stack.enter_context(
                    p4gf_git_repo_lock.write_lock(repo_name, upgrade=True))
                print("Test 1:")
                print_lock_status(p4, server_id)
                p4gf_p4key.set(p4, pushid_key_name, '2')
                p4gf_p4key.set(p4, status_key_name,
                               'Push 2 failed: some error')
                # Finally lets set the P4GF_P4KEY_LOCK_VIEW - the least likley to be stale
                p4gf_p4key.set(p4, lock2.lock_key, '1')
                print("Test 2:")
                print_lock_status(p4, server_id)
                # Cant exit the ExistStack unless we clean this
                p4gf_p4key.delete(p4, lock2.lock_key)
            # Clean up this lock so the test may be run again
            p4gf_p4key.delete(p4, lock2.owners_key)
        # remove test keys
        p4gf_p4key.delete(p4, status_key_name)
        p4gf_p4key.delete(p4, pushid_key_name)
    else:
        print_lock_status(p4, server_id)
コード例 #28
0
def delete_client(args, p4, client_name, metrics, prune_objs=True):
    """Delete the named Perforce client and its workspace. Raises
    P4Exception if the client is not present, or the client configuration is
    not set up as expected.

    Keyword arguments:
    args        -- parsed command line arguments
    p4          -- Git user's Perforce client
    client_name -- name of client to be deleted
    metrics     -- DeletionMetrics for collecting resulting metrics
    prune_objs  -- if True, delete associated objects from cache

    """
    # pylint: disable=R0912,R0915
    group_list = [p4gf_const.P4GF_GROUP_VIEW_PULL, p4gf_const.P4GF_GROUP_VIEW_PUSH]
    p4.user = p4gf_const.P4GF_USER

    print_verbose(args, _("Checking for client '{}'...").format(client_name))
    if not p4gf_util.spec_exists(p4, 'client', client_name):
        raise P4.P4Exception(_("No such client '{}' defined")
                             .format(client_name))
    view_name = p4gf_util.client_to_view_name(client_name)
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
    p4gf_util.ensure_spec_values(p4, 'client', client_name, {'Root': view_dirs.p4root})

    view_lock = None  # We're clobbering and deleting. Overrule locks.
    with p4gf_context.create_context(view_name, view_lock) as ctx:
        command_path = ctx.client_view_path()

        homedir = os.path.expanduser('~')
        raise_if_homedir(homedir, view_name, view_dirs.view_container)

        # Scan for objects associated only with this view so we can remove them.
        objects_to_delete = []
        if prune_objs:
            objects_to_delete = _find_client_commit_objects(args, p4, view_name)

        # Do we have a repo config file to delete?
        config_file = p4gf_config.depot_path_repo(view_name) + '*'
        config_file_exists = p4gf_util.depot_file_exists(p4, config_file)

        # What counters shall we delete?
        counter_list = []
        counter_list.append(p4gf_context.calc_last_copied_change_counter_name(
                            view_name, p4gf_util.get_server_id()))
        for spec in p4.run('counters', '-u', '-e', "git-fusion-index-last-{},*"
                                                   .format(view_name)):
            counter_list.append(spec['counter'])
        for spec in p4.run('counters', '-u', '-e', "git-fusion-index-branch-{},*"
                                                   .format(view_name)):
            counter_list.append(spec['counter'])

        if not args.delete:
            print(NTR('p4 sync -f {}#none').format(command_path))
            print(NTR('p4 client -f -d {}').format(client_name))
            print(NTR('rm -rf {}').format(view_dirs.view_container))
            print(NTR('Deleting {} objects from //{}/objects/...').format(
                len(objects_to_delete), p4gf_const.P4GF_DEPOT))
            for group_template in group_list:
                group = group_template.format(view=view_name)
                print(NTR('p4 group -a -d {}').format(group))
            for c in counter_list:
                print(NTR('p4 counter -u -d {}').format(c))

            if config_file_exists:
                print(NTR('p4 sync -f {}').format(config_file))
                print(NTR('p4 delete  {}').format(config_file))
                print(NTR('p4 submit -d "Delete repo config for {view_name}" {config_file}')
                      .format(view_name=view_name, config_file=config_file))
        else:
            print_verbose(args, NTR('Removing client files for {}...').format(client_name))
            ctx.p4.run('sync', '-fq', command_path + '#none')
            print_verbose(args, NTR('Deleting client {}...').format(client_name))
            p4.run('client', '-df', client_name)
            metrics.clients += 1
            print_verbose(args, NTR("Deleting repo {0}'s directory {1}...").format(view_name,
                view_dirs.view_container))
            _remove_tree(view_dirs.view_container, contents_only=False)
            metrics.files += _delete_files(p4, objects_to_delete, view_name)
            for group_template in group_list:
                _delete_group(args, p4, group_template.format(view=view_name), metrics)
            for c in counter_list:
                _delete_counter(p4, c, metrics)

            if config_file_exists:
                p4gf_util.p4run_logged(p4, ['sync', '-fq', config_file])
                with p4gf_util.NumberedChangelist(
                        p4=p4, description=_("Delete repo config for '{}'")
                                           .format(view_name)) as nc:
                    nc.p4run(["delete", config_file])
                    nc.submit()
コード例 #29
0
 def _get_server_repo_config_rev(self):
     """Get the config file rev for the repo from the p4key."""
     key = p4gf_const.P4GF_P4KEY_REPO_SERVER_CONFIG_REV.format(
         repo_name=self.repo_name, server_id=p4gf_util.get_server_id())
     return p4gf_util.get_p4key(self.p4, key)
コード例 #30
0
ファイル: p4gf_tag.py プロジェクト: spearhead-ea/git-fusion
def _last_copied_tag_counter_name(ctx):
    '''
    Return the name of a counter that holds the latest tag changelist
    number for this Git Fusion server.
    '''
    return _calc_last_copied_tag_counter_name(ctx.config.view_name, p4gf_util.get_server_id())
コード例 #31
0
def exclusive_host_view_lock(p4, view_name):
    '''Return an exclusive lock for the desired view, specific to the current host.
    '''
    host_name = p4gf_util.get_server_id()
    return ExclusiveViewLock(p4, host_name, view_name)
コード例 #32
0
def delete_client(args, p4, client_name, metrics, prune_objs=True):
    """Delete the named Perforce client and its workspace. Raises
    P4Exception if the client is not present, or the client configuration is
    not set up as expected.

    Keyword arguments:
    args        -- parsed command line arguments
    p4          -- Git user's Perforce client
    client_name -- name of client to be deleted
    metrics     -- DeletionMetrics for collecting resulting metrics
    prune_objs  -- if True, delete associated objects from cache

    """
    # pylint: disable=R0912,R0915
    group_list = [
        p4gf_const.P4GF_GROUP_VIEW_PULL, p4gf_const.P4GF_GROUP_VIEW_PUSH
    ]
    p4.user = p4gf_const.P4GF_USER

    print_verbose(args, _("Checking for client '{}'...").format(client_name))
    if not p4gf_util.spec_exists(p4, 'client', client_name):
        raise P4.P4Exception(
            _("No such client '{}' defined").format(client_name))
    view_name = p4gf_util.client_to_view_name(client_name)
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
    p4gf_util.ensure_spec_values(p4, 'client', client_name,
                                 {'Root': view_dirs.p4root})

    view_lock = None  # We're clobbering and deleting. Overrule locks.
    with p4gf_context.create_context(view_name, view_lock) as ctx:
        command_path = ctx.client_view_path()

        homedir = os.path.expanduser('~')
        raise_if_homedir(homedir, view_name, view_dirs.view_container)

        # Scan for objects associated only with this view so we can remove them.
        objects_to_delete = []
        if prune_objs:
            objects_to_delete = _find_client_commit_objects(
                args, p4, view_name)

        # Do we have a repo config file to delete?
        config_file = p4gf_config.depot_path_repo(view_name) + '*'
        config_file_exists = p4gf_util.depot_file_exists(p4, config_file)

        # What counters shall we delete?
        counter_list = []
        counter_list.append(
            p4gf_context.calc_last_copied_change_counter_name(
                view_name, p4gf_util.get_server_id()))
        for spec in p4.run('counters', '-u', '-e',
                           "git-fusion-index-last-{},*".format(view_name)):
            counter_list.append(spec['counter'])
        for spec in p4.run('counters', '-u', '-e',
                           "git-fusion-index-branch-{},*".format(view_name)):
            counter_list.append(spec['counter'])

        if not args.delete:
            print(NTR('p4 sync -f {}#none').format(command_path))
            print(NTR('p4 client -f -d {}').format(client_name))
            print(NTR('rm -rf {}').format(view_dirs.view_container))
            print(
                NTR('Deleting {} objects from //{}/objects/...').format(
                    len(objects_to_delete), p4gf_const.P4GF_DEPOT))
            for group_template in group_list:
                group = group_template.format(view=view_name)
                print(NTR('p4 group -a -d {}').format(group))
            for c in counter_list:
                print(NTR('p4 counter -u -d {}').format(c))

            if config_file_exists:
                print(NTR('p4 sync -f {}').format(config_file))
                print(NTR('p4 delete  {}').format(config_file))
                print(
                    NTR('p4 submit -d "Delete repo config for {view_name}" {config_file}'
                        ).format(view_name=view_name, config_file=config_file))
        else:
            print_verbose(
                args,
                NTR('Removing client files for {}...').format(client_name))
            ctx.p4.run('sync', '-fq', command_path + '#none')
            print_verbose(args,
                          NTR('Deleting client {}...').format(client_name))
            p4.run('client', '-df', client_name)
            metrics.clients += 1
            print_verbose(
                args,
                NTR("Deleting repo {0}'s directory {1}...").format(
                    view_name, view_dirs.view_container))
            _remove_tree(view_dirs.view_container, contents_only=False)
            metrics.files += _delete_files(p4, objects_to_delete, view_name)
            for group_template in group_list:
                _delete_group(args, p4, group_template.format(view=view_name),
                              metrics)
            for c in counter_list:
                _delete_counter(p4, c, metrics)

            if config_file_exists:
                p4gf_util.p4run_logged(p4, ['sync', '-fq', config_file])
                with p4gf_util.NumberedChangelist(
                        p4=p4,
                        description=_("Delete repo config for '{}'").format(
                            view_name)) as nc:
                    nc.p4run(["delete", config_file])
                    nc.submit()