def init_repo(p4,
              view_name,
              view_lock,
              charset=None,
              enable_mismatched_rhs=False,
              view_name_p4client=None,
              handle_imports=True):
    '''
    Create view and repo if necessary. Does NOT copy p4 to the repo
    (that's p4gf_copy_p2g's job). Returns one of the INIT_REPO_* constants.

    This is p4gf_auth_server's entry point into init_repo, called in response
    to a 'git clone'.

    view_name is the internal view_name with special chars already translated

    view_lock           CounterLock mutex that prevents other processes from
                        touching this repo, whether on this Git Fusion server
                        or another.
    '''
    LOG.debug("init_repo : view_name {1} view_name_p4client {1}".format(
        view_name, view_name_p4client))
    client_name = p4gf_util.view_to_client_name(view_name)
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)

    result = _create_p4_client(p4, view_name, client_name, view_dirs.p4root,
                               enable_mismatched_rhs, view_name_p4client,
                               handle_imports)
    if result > INIT_REPO_OK:
        return result
    create_perm_groups(p4, view_name)
    with p4gf_context.create_context(view_name, view_lock) as ctx:
        p4gf_config.create_file_repo(ctx, view_name, charset)
        if ctx.client_exclusions_added:
            _print_stderr(
                _("The referenced client view contains implicit exclusions."
                  "\nThe Git Fusion config will contain these as explicit exclusions."
                  ))
        p4gf_copy_p2g.create_git_repo(ctx, view_dirs.GIT_DIR)
    create_p4_client_root(view_dirs.p4root)
    p4gf_rc.update_file(view_dirs.rcfile, client_name, view_name)
    if result == INIT_REPO_OK:
        LOG.debug("repository creation for %s complete", view_name)
    # return the result of creating the client, to indicate if the client
    # had already been set up or not
    return result
def copy_p2g_ctx(ctx, start=None):
    """Using the given context, copy its view from Perforce to Git.

    Common code for p4gf_auth_server.py and p4gf_init_repo.py for setting up
    the eventual call to copy_p2g."""

    view_name = ctx.config.view_name

    # Find directory paths to feed to git.
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(ctx.p4gf)
    ctx.view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)

    # cd into the work directory. Not all git functions react well to --work-tree=xxxx.
    os.chdir(ctx.view_dirs.GIT_WORK_TREE)

    # Fill git with content from Perforce.
    copy_p2g(ctx, start)
Example #3
0
def copy_p2g_ctx(ctx, start=None):
    """Using the given context, copy its view from Perforce to Git.

    Common code for p4gf_auth_server.py and p4gf_init_repo.py for setting up
    the eventual call to copy_p2g."""

    view_name = ctx.config.view_name

    # Find directory paths to feed to git.
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(ctx.p4gf)
    ctx.view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)

    # cd into the work directory. Not all git functions react well to --work-tree=xxxx.
    os.chdir(ctx.view_dirs.GIT_WORK_TREE)

    # Fill git with content from Perforce.
    copy_p2g(ctx, start)
Example #4
0
def _list_for_server():
    '''
    Return list of repos that have been copied to the given Git Fusion
    server.

    "have been copied" here means "has a .git-fusion/views/<view_name>/
    directory on this server."
    '''
    p4 = p4gf_create_p4.create_p4(client=p4gf_util.get_object_client_name())
    result = []
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)

    for view_name in p4gf_util.view_list(p4):
        view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
        if os.path.exists(view_dirs.GIT_DIR):
            result.append(view_name)
    p4gf_create_p4.destroy(p4)
    return result
Example #5
0
def _list_for_server():
    '''
    Return list of repos that have been copied to the given Git Fusion
    server.

    "have been copied" here means "has a .git-fusion/views/<view_name>/
    directory on this server."
    '''
    p4 = p4gf_create_p4.create_p4(client=p4gf_util.get_object_client_name())
    result = []
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)

    for view_name in p4gf_util.view_list(p4):
        view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
        if os.path.exists(view_dirs.GIT_DIR):
            result.append(view_name)
    p4gf_create_p4.destroy(p4)
    return result
def init_repo(p4
             , view_name
             , view_lock
             , charset=None
             , enable_mismatched_rhs=False
             , view_name_p4client=None
             , handle_imports=True):
    '''
    Create view and repo if necessary. Does NOT copy p4 to the repo
    (that's p4gf_copy_p2g's job). Returns one of the INIT_REPO_* constants.

    This is p4gf_auth_server's entry point into init_repo, called in response
    to a 'git clone'.

    view_name is the internal view_name with special chars already translated

    view_lock           CounterLock mutex that prevents other processes from
                        touching this repo, whether on this Git Fusion server
                        or another.
    '''
    LOG.debug("init_repo : view_name {1} view_name_p4client {1}".format(
        view_name, view_name_p4client))
    client_name = p4gf_util.view_to_client_name(view_name)
    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)

    result = _create_p4_client(p4, view_name, client_name, view_dirs.p4root,
                               enable_mismatched_rhs, view_name_p4client, handle_imports)
    if result > INIT_REPO_OK:
        return result
    create_perm_groups(p4, view_name)
    with p4gf_context.create_context(view_name, view_lock) as ctx:
        p4gf_config.create_file_repo(ctx, view_name, charset)
        if ctx.client_exclusions_added:
            _print_stderr(_("The referenced client view contains implicit exclusions."
                            "\nThe Git Fusion config will contain these as explicit exclusions."))
        p4gf_copy_p2g.create_git_repo(ctx, view_dirs.GIT_DIR)
    create_p4_client_root(view_dirs.p4root)
    p4gf_rc.update_file(view_dirs.rcfile, client_name, view_name)
    if result == INIT_REPO_OK:
        LOG.debug("repository creation for %s complete", view_name)
    # return the result of creating the client, to indicate if the client
    # had already been set up or not
    return result
Example #7
0
    def _read_user_map(self):
        """
        Reads the user map file from Perforce into a list of tuples,
        consisting of username, email address, and full name. If no
        such file exists, an empty list is returned.

        Returns a list of 3-tuples: (p4user, email, fullname)
        """
        usermap = []
        root = p4gf_util.p4_to_p4gf_dir(self.p4)
        mappath = root + '/users/p4gf_usermap'

        global _user_map_synced
        if not _user_map_synced:
            # don't let a writable usermap file get in our way
            self.p4.run('sync', '-fq', mappath)
            _user_map_synced = True

        if not os.path.exists(mappath):
            return usermap

        with open(mappath) as mf:
            no_folding = self._is_case_sensitive()
            for line in mf:
                if not line:
                    continue
                line = line.strip()
                if not line or line[0] == '#':
                    continue
                m = USERMAP_REGEX.search(line)
                if not m:
                    LOG.debug('No match: {}'.format(line))
                    continue

                p4user   = m.group(1) if no_folding else m.group(1).casefold()
                email    = m.group(2)
                _validate_email(email)
                fullname = p4gf_util.dequote(m.group(3))
                usermap.append((p4user, email, fullname))
        return usermap
Example #8
0
def cleanup_client(ctx, view_name):
    """Clean up the failed client and workspace after an error occurs while
    creating the initial clone. If the client does not exist, nothing is done.
    """
    client_name = p4gf_const.P4GF_CLIENT_PREFIX + view_name
    if not p4gf_util.spec_exists(ctx.p4, 'client', client_name):
        return

    LOG.debug('cleaning up failed view {}'.format(view_name))
    command_path = ctx.client_view_path()

    p4gf_dir = p4gf_util.p4_to_p4gf_dir(ctx.p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)

    ctx.p4.run('sync', '-fq', command_path + '#none')
    ctx.p4.run('client', '-df', client_name)
    for vdir in [view_dirs.view_container]:
        LOG.debug('removing view directory {}'.format(vdir))
        if os.path.isdir(vdir):
            shutil.rmtree(vdir)
        elif os.path.isfile(vdir):
            os.remove(vdir)
def init_repo(p4, view_name):
    """Create view and repo if necessary. Does NOT copy p4 to the repo
    (that's p4gf_copy_p2g's job). Returns one of the INIT_REPO_* constants.
    """

    client_name = p4gf_context.view_to_client_name(view_name)

    p4gf_dir    = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
    result = create_p4_client(p4, view_name, client_name, view_dirs.p4root)
    if result > INIT_REPO_OK:
        return result
    create_perm_groups(p4, view_name)
    p4gf_copy_p2g.create_git_repo(view_dirs.GIT_DIR)
    ensure_deny_rewind(view_dirs.GIT_WORK_TREE)
    install_hook(view_dirs.GIT_DIR)
    create_p4_client_root(view_dirs.p4root)
    p4gf_rc.update_file(view_dirs.rcfile, client_name, view_name)
    LOG.debug("repository creation for %s complete", view_name)
    # return the result of creating the client, to indicate if the client
    # had already been set up or not
    return result
def cleanup_client(ctx, view_name):
    """Clean up the failed client and workspace after an error occurs while
    creating the initial clone. If the client does not exist, nothing is done.
    """
    client_name = p4gf_const.P4GF_CLIENT_PREFIX + view_name
    if not p4gf_util.spec_exists(ctx.p4, 'client', client_name):
        return

    LOG.debug('cleaning up failed view {}'.format(view_name))
    command_path = ctx.client_view_path()

    p4gf_dir = p4gf_util.p4_to_p4gf_dir(ctx.p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)

    ctx.p4.run('sync', '-fq', command_path + '#none')
    ctx.p4.run('client', '-df', client_name)
    for vdir in [view_dirs.view_container]:
        LOG.debug('removing view directory {}'.format(vdir))
        if os.path.isdir(vdir):
            shutil.rmtree(vdir)
        elif os.path.isfile(vdir):
            os.remove(vdir)
def delete_client(args, p4, client_name):
    """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

    """
    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 = client_name[len(p4gf_const.P4GF_CLIENT_PREFIX):]
    view_lock = None  # We're clobbering and deleting. Overrule locks.
    try:
        ctx = p4gf_context.create_context(view_name, view_lock)
    except RuntimeError:
        # not a conforming Git Fusion client, ignore it
        return
    command_path = ctx.client_view_path()

    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
    rm_list = [view_dirs.view_container]
    homedir = os.path.expanduser('~')
    raise_if_homedir(homedir, view_name, rm_list)

    # Scan for objects associated only with this view so we can either remove
    # them completely or update their 'views' attribute appropriately.
    p4.handler = FilterViewFstatHandler(view_name)
    p4.run("fstat", "-Oa", "-T", "depotFile, attr-views",
           "//.git-fusion/objects/...")
    objects_to_delete = p4.handler.files_to_delete
    objects_to_modify = p4.handler.files_to_modify
    p4.handler = None

    if not args.delete:
        print("p4 sync -f {}#none".format(command_path))
        print("p4 client -f -d {}".format(client_name))
        for d in rm_list:
            print("rm -rf {}".format(d))
        for to_delete in objects_to_delete:
            print("p4 obliterate -y {}".format(to_delete))
        if objects_to_modify:
            for (fname, views) in objects_to_modify:
                print("attribute -p -n views -v {} {}".format(views, fname))
        for group_template in group_list:
            group = group_template.format(view=view_name)
            print("p4 group -a -d {}".format(group))
        print('p4 counter -u -d {}'.format(
            p4gf_lock.view_lock_name(view_name)))

    else:
        print_verbose(args,
                      "Removing client files for {}...".format(client_name))
        ctx.p4.run('sync', '-fq', command_path + '#none')
        print_verbose(args, "Deleting client {}...".format(client_name))
        p4.run('client', '-df', client_name)
        for d in rm_list:
            remove_file_or_dir(args, view_name, d)
        bite_size = 1000
        while len(objects_to_delete):
            to_delete = objects_to_delete[:bite_size]
            objects_to_delete = objects_to_delete[bite_size:]
            p4.run("obliterate", "-y", to_delete)
        if objects_to_modify:
            for (fname, views) in objects_to_modify:
                p4.run("edit", fname)
                p4.run("attribute", "-p", "-n", "views", "-v", views, fname)
            p4.run("submit", "-d",
                   "'Removing {} from views attribute'".format(view_name))
        for group_template in group_list:
            delete_group(args, p4, group_template.format(view=view_name))
        _delete_counter(p4, p4gf_lock.view_lock_name(view_name))
def delete_client(args, p4, client_name):
    """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

    """
    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 = client_name[len(p4gf_const.P4GF_CLIENT_PREFIX):]
    view_lock = None  # We're clobbering and deleting. Overrule locks.
    try:
        ctx = p4gf_context.create_context(view_name, view_lock)
    except RuntimeError:
        # not a conforming Git Fusion client, ignore it
        return
    command_path = ctx.client_view_path()

    p4gf_dir = p4gf_util.p4_to_p4gf_dir(p4)
    view_dirs = p4gf_view_dirs.from_p4gf_dir(p4gf_dir, view_name)
    rm_list = [view_dirs.view_container]
    homedir = os.path.expanduser('~')
    raise_if_homedir(homedir, view_name, rm_list)

    # Scan for objects associated only with this view so we can either remove
    # them completely or update their 'views' attribute appropriately.
    p4.handler = FilterViewFstatHandler(view_name)
    p4.run("fstat", "-Oa", "-T", "depotFile, attr-views", "//.git-fusion/objects/...")
    objects_to_delete = p4.handler.files_to_delete
    objects_to_modify = p4.handler.files_to_modify
    p4.handler = None

    if not args.delete:
        print("p4 sync -f {}#none".format(command_path))
        print("p4 client -f -d {}".format(client_name))
        for d in rm_list:
            print("rm -rf {}".format(d))
        for to_delete in objects_to_delete:
            print("p4 obliterate -y {}".format(to_delete))
        if objects_to_modify:
            for (fname, views) in objects_to_modify:
                print("attribute -p -n views -v {} {}".format(views, fname))
        for group_template in group_list:
            group = group_template.format(view=view_name)
            print("p4 group -a -d {}".format(group))
        print('p4 counter -u -d {}'.format(p4gf_lock.view_lock_name(view_name)))

    else:
        print_verbose(args, "Removing client files for {}...".format(client_name))
        ctx.p4.run('sync', '-fq', command_path + '#none')
        print_verbose(args, "Deleting client {}...".format(client_name))
        p4.run('client', '-df', client_name)
        for d in rm_list:
            remove_file_or_dir(args, view_name, d)
        bite_size = 1000
        while len(objects_to_delete):
            to_delete = objects_to_delete[:bite_size]
            objects_to_delete = objects_to_delete[bite_size:]
            p4.run("obliterate", "-y", to_delete)
        if objects_to_modify:
            for (fname, views) in objects_to_modify:
                p4.run("edit", fname)
                p4.run("attribute", "-p", "-n", "views", "-v", views, fname)
            p4.run("submit", "-d", "'Removing {} from views attribute'".format(view_name))
        for group_template in group_list:
            delete_group(args, p4, group_template.format(view=view_name))
        _delete_counter(p4, p4gf_lock.view_lock_name(view_name))
Example #13
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()
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()