Obtenez rapidement une liste de tous les externes svn:pour un dépôt svn distant

nous avons un dépôt svn avec beaucoup de répertoires et de fichiers et notre système de compilation doit être capable de trouver toutes les propriétés svn:externals, récursivement pour une branche dans le dépôt, avant de le vérifier. Nous utilisons actuellement:

svn propget svn:externals -R http://url.of.repo/Branch

cela a pris énormément de temps et c'est un véritable hog de bande passante. Il semble que le client reçoit tous les accessoires pour tout ce qui se trouve dans la déclaration et qu'il effectue le filtrage localement (bien que je ne l'ai pas confirmé avec wireshark). Est-il un moyen plus rapide de faire cela? De préférence, un moyen de faire en sorte que le serveur ne renvoie que les données désirées.

24
demandé sur NeoSkye 2012-04-17 04:16:36
la source

6 ответов

comme vous l'avez mentionné, cela consomme de la bande passante réseau. Toutefois, si vous avez accès au serveur où ces dépôts sont hébergés, vous pouvez l'exécuter à l'aide de file:// protocole. Il est prouvé qu'il est plus rapide et ne consomme pas le réseau.

svn propget svn:externals -R file:///path/to/repo/Branch

de plus, si vous avez la copie de travail complète en place, vous pouvez également l'exécuter dans votre WC.

svn propget svn:externals -R /path/to/WC

espérons que cela vous aidera à obtenir les résultats plus rapidement!.

25
répondu Jeyanthan I 2017-08-21 15:01:46
la source

j'ai finalement trouvé une solution. J'ai décidé de scinder la requête en plusieurs petites requêtes svn puis de faire de chacune d'elles une tâche à exécuter par un pool de threads. Ce type de requête bloque le serveur svn, mais dans notre cas, le serveur svn est sur le réseau local et cette requête n'est faite que pendant les compilations complètes, donc cela ne semble pas poser de problème.

import os
import sys
import threading
import ThreadPool

thread_pool = ThreadPool.ThreadPool(8)
externs_dict = {}
externs_lock = threading.Lock()

def getExternRev( path, url ):
    cmd = 'svn info "%s"' % url
    pipe = os.popen(cmd, 'r')
    data = pipe.read().splitlines()

    #Harvest last changed rev
    for line in data:
        if "Last Changed Rev" in line:
            revision = line.split(":")[1].strip()
            externs_lock.acquire()
            externs_dict[path] = (url, revision)
            externs_lock.release()

def getExterns(url, base_dir):
    cmd = 'svn propget svn:externals "%s"' % url
    pipe = os.popen(cmd, 'r')
    data = pipe.read().splitlines()
    pipe.close()

    for line in data:
        if line:
            line = line.split()
            path = base_dir + line[0]
            url = line[1]
            thread_pool.add_task( getExternRev, path, url )

def processDir(url, base_dir):
    thread_pool.add_task( getExterns, url, base_dir )

    cmd = 'svn list "%s"' % url
    pipe = os.popen(cmd, 'r')
    listing = pipe.read().splitlines()
    pipe.close()

    dir_list = []
    for node in listing:
        if node.endswith('/'):
            dir_list.append(node)

    for node in dir_list:
        #externs_data.extend( analyzePath( url + node, base_dir + node ) )
        thread_pool.add_task( processDir, url+node, base_dir+node )

def analyzePath(url, base_dir = ''):
    thread_pool.add_task( processDir, url, base_dir )
    thread_pool.wait_completion()


analyzePath( "http://url/to/repository" )
print externs_dict
2
répondu NeoSkye 2012-04-23 22:28:36
la source

il est lent à cause du commutateur-R; tous les répertoires de votre chemin de dépôt sont recherchés de façon récursive pour la propriété, ce qui est beaucoup de travail.

0
répondu Argeman 2012-04-20 17:31:01
la source

pas la solution idéale (peut avoir des effets secondaires) et ne pas répondre à votre problème, mais

vous pouvez réécrire toutes les définitions externes et ajouter (réécrire) dans un endroit commun, connu - de cette façon, vous éliminerez la récursion dans pg après le changement

0
répondu Lazy Badger 2013-05-04 01:46:17
la source

si cela ne vous dérange pas d'utiliser Python et la bibliothèque pysvn, voici un programme complet en ligne de commande que J'utilise pour SVN externals:

"""
@file
@brief SVN externals utilities.
@author Lukasz Matecki
"""
import sys
import os
import pysvn
import argparse

class External(object):

    def __init__(self, parent, remote_loc, local_loc, revision):
        self.parent = parent
        self.remote_loc = remote_loc
        self.local_loc = local_loc
        self.revision = revision

    def __str__(self):
        if self.revision.kind == pysvn.opt_revision_kind.number:
            return """\
Parent:     {0}
Source:     {1}@{2}
Local name: {3}""".format(self.parent, self.remote_loc, self.revision.number, self.local_loc)
        else:
            return """\
Parent:     {0}
Source:     {1} 
Local name: {2}""".format(self.parent, self.remote_loc, self.local_loc)


def find_externals(client, repo_path, external_path=None):
    """
    @brief Find SVN externals.
    @param client (pysvn.Client) The client to use.
    @param repo_path (str) The repository path to analyze.
    @param external_path (str) The URL of the external to find; if omitted, all externals will be searched.
    @returns [External] The list of externals descriptors or empty list if none found.
    """
    repo_root = client.root_url_from_path(repo_path)

    def parse(ext_prop):
        for parent in ext_prop:
            external = ext_prop[parent]
            for line in external.splitlines():
                path, name = line.split()
                path = path.replace("^", repo_root)
                parts = path.split("@")
                if len(parts) > 1:
                    url = parts[0]
                    rev = pysvn.Revision(pysvn.opt_revision_kind.number, int(parts[1]))
                else:
                    url = parts[0]
                    rev = pysvn.Revision(pysvn.opt_revision_kind.head)
                retval = External(parent, url, name, rev)
                if external_path and not external_path == url:
                    continue
                else:
                    yield retval

    for entry in client.ls(repo_path, recurse=True):
        if entry["kind"] == pysvn.node_kind.dir and entry["has_props"] == True:
            externals = client.propget("svn:externals", entry["name"])
            if externals:
                for e in parse(externals):
                    yield e


def check_externals(client, externals_list):
    for i, e in enumerate(externals_list):
        url = e.remote_loc
        rev = e.revision
        try:
            info = client.info2(url, revision=rev, recurse=False)
            props = info[0][1]
            url = props.URL
            print("[{0}] Existing:\n{1}".format(i + 1, "\n".join(["   {0}".format(line) for line in str(e).splitlines()])))
        except:
            print("[{0}] Not found:\n{1}".format(i + 1, "\n".join(["   {0}".format(line) for line in str(e).splitlines()])))

def main(cmdargs):
    parser = argparse.ArgumentParser(description="SVN externals processing.",
                                     formatter_class=argparse.RawDescriptionHelpFormatter,
                                     prefix_chars='-+')

    SUPPORTED_COMMANDS = ("check", "references")

    parser.add_argument(
        "action",
        type=str,
        default="check",
        choices=SUPPORTED_COMMANDS,
        help="""\
the operation to execute:
   'check' to validate all externals in a given location;
   'references' to print all references to a given location""")

    parser.add_argument(
        "url",
        type=str,
        help="the URL to operate on")

    parser.add_argument(
        "--repo", "-r",
        dest="repo",
        type=str,
        default=None,
        help="the repository (or path within) to perform the operation on, if omitted is inferred from url parameter")

    args = parser.parse_args()

    client = pysvn.Client()

    if args.action == "check":
        externals = find_externals(client, args.url)
        check_externals(client, externals)
    elif args.action == "references":
        if args.repo:
            repo_root = args.repo
        else:
            repo_root = client.root_url_from_path(args.url)
        for i, e in enumerate(find_externals(client, repo_root, args.url)):
            print("[{0}] Reference:\n{1}".format(i + 1, "\n".join(["   {0}".format(line) for line in str(e).splitlines()])))

if __name__ == "__main__":
    sys.exit(main(sys.argv))

cela devrait fonctionner en Python 2 et Python 3. Vous pouvez l'utiliser comme ceci (adresses supprimé):

python svn_externals.py references https://~~~~~~~~~~~~~~/cmd_utils.py
[1] Reference:
   Parent:     https://~~~~~~~~~~~~~~/BEFORE_MK2/scripts/utils
   Source:     https://~~~~~~~~~~~~~~/tools/python/cmd_utils.py
   Local name: cmd_utils.py
[2] Reference:
   Parent:     https://~~~~~~~~~~~~~~/VTB-1425_PCU/scripts/utils
   Source:     https://~~~~~~~~~~~~~~/tools/python/cmd_utils.py
   Local name: cmd_utils.py
[3] Reference:
   Parent:     https://~~~~~~~~~~~~~~/scripts/utils
   Source:     https://~~~~~~~~~~~~~~/tools/python/cmd_utils.py
   Local name: cmd_utils.py

en ce qui concerne la performance, cela fonctionne assez rapidement (bien que mon dépôt soit assez petit). Vous devez vérifier par vous-même.

0
répondu lutecki 2017-03-25 12:53:39
la source

Je ne sais pas où j'ai trouvé ce bijou, mais il est très utile de voir le alias avec externals:

Windows:
    svn status . | findstr /R "^X"

Linux/Unix:
    svn status . | grep -E "^X"
0
répondu Marcel Petrick 2018-04-20 15:07:41
la source

Autres questions sur