Frage

Wenn ich 20 Verzeichnisse unter „trunk/“ mit vielen Dateien in jedem hätte und nur 3 dieser Verzeichnisse benötige, wäre es dann möglich, einen Subversion-Checkout mit nur diesen 3 Verzeichnissen unter „trunk“ durchzuführen?

War es hilfreich?

Lösung

Subversion 1.5 führt Sparse-Checkouts ein, was für Sie möglicherweise nützlich sein könnte.Von dem Dokumentation:

... spärliche Verzeichnisse (oder flache Kassen) ...ermöglicht es Ihnen, eine Arbeitskopie – oder einen Teil einer Arbeitskopie – einfacher auszuchecken als mit einer vollständigen Rekursion, mit der Freiheit, zuvor ignorierte Dateien und Unterverzeichnisse zu einem späteren Zeitpunkt einzufügen.

Andere Tipps

Tatsächlich sieht es dank der Kommentare zu meinem Beitrag hier so aus spärliche Verzeichnisse sind der richtige Weg.Ich glaube, Folgendes sollte es tun:

svn checkout --depth empty http://svnserver/trunk/proj
svn update --set-depth infinity proj/foo
svn update --set-depth infinity proj/bar
svn update --set-depth infinity proj/baz

Alternative, --depth immediates anstatt empty Checkt Dateien und Verzeichnisse aus trunk/proj ohne ihren Inhalt.Auf diese Weise können Sie sehen, welche Verzeichnisse im Repository vorhanden sind.


Wie in der Antwort von @zigdon erwähnt, können Sie auch einen nicht rekursiven Checkout durchführen.Dies ist eine ältere und weniger flexible Methode, um einen ähnlichen Effekt zu erzielen:

svn checkout --non-recursive http://svnserver/trunk/proj
svn update trunk/foo
svn update trunk/bar
svn update trunk/baz

Ich habe ein Skript geschrieben, um komplexe, spärliche Checkouts zu automatisieren.

#!/usr/bin/env python

'''
This script makes a sparse checkout of an SVN tree in the current working directory.

Given a list of paths in an SVN repository, it will:
1. Checkout the common root directory
2. Update with depth=empty for intermediate directories
3. Update with depth=infinity for the leaf directories
'''

import os
import getpass
import pysvn

__author__ = "Karl Ostmo"
__date__ = "July 13, 2011"

# =============================================================================

# XXX The os.path.commonprefix() function does not behave as expected!
# See here: http://mail.python.org/pipermail/python-dev/2002-December/030947.html
# and here: http://nedbatchelder.com/blog/201003/whats_the_point_of_ospathcommonprefix.html
# and here (what ever happened?): http://bugs.python.org/issue400788
from itertools import takewhile
def allnamesequal(name):
    return all(n==name[0] for n in name[1:])

def commonprefix(paths, sep='/'):
    bydirectorylevels = zip(*[p.split(sep) for p in paths])
    return sep.join(x[0] for x in takewhile(allnamesequal, bydirectorylevels))

# =============================================================================
def getSvnClient(options):

    password = options.svn_password
    if not password:
        password = getpass.getpass('Enter SVN password for user "%s": ' % options.svn_username)

    client = pysvn.Client()
    client.callback_get_login = lambda realm, username, may_save: (True, options.svn_username, password, True)
    return client

# =============================================================================
def sparse_update_with_feedback(client, new_update_path):
    revision_list = client.update(new_update_path, depth=pysvn.depth.empty)

# =============================================================================
def sparse_checkout(options, client, repo_url, sparse_path, local_checkout_root):

    path_segments = sparse_path.split(os.sep)
    path_segments.reverse()

    # Update the middle path segments
    new_update_path = local_checkout_root
    while len(path_segments) > 1:
        path_segment = path_segments.pop()
        new_update_path = os.path.join(new_update_path, path_segment)
        sparse_update_with_feedback(client, new_update_path)
        if options.verbose:
            print "Added internal node:", path_segment

    # Update the leaf path segment, fully-recursive
    leaf_segment = path_segments.pop()
    new_update_path = os.path.join(new_update_path, leaf_segment)

    if options.verbose:
        print "Will now update with 'recursive':", new_update_path
    update_revision_list = client.update(new_update_path)

    if options.verbose:
        for revision in update_revision_list:
            print "- Finished updating %s to revision: %d" % (new_update_path, revision.number)

# =============================================================================
def group_sparse_checkout(options, client, repo_url, sparse_path_list, local_checkout_root):

    if not sparse_path_list:
        print "Nothing to do!"
        return

    checkout_path = None
    if len(sparse_path_list) > 1:
        checkout_path = commonprefix(sparse_path_list)
    else:
        checkout_path = sparse_path_list[0].split(os.sep)[0]



    root_checkout_url = os.path.join(repo_url, checkout_path).replace("\\", "/")
    revision = client.checkout(root_checkout_url, local_checkout_root, depth=pysvn.depth.empty)

    checkout_path_segments = checkout_path.split(os.sep)
    for sparse_path in sparse_path_list:

        # Remove the leading path segments
        path_segments = sparse_path.split(os.sep)
        start_segment_index = 0
        for i, segment in enumerate(checkout_path_segments):
            if segment == path_segments[i]:
                start_segment_index += 1
            else:
                break

        pruned_path = os.sep.join(path_segments[start_segment_index:])
        sparse_checkout(options, client, repo_url, pruned_path, local_checkout_root)

# =============================================================================
if __name__ == "__main__":

    from optparse import OptionParser
    usage = """%prog  [path2] [more paths...]"""

    default_repo_url = "http://svn.example.com/MyRepository"
    default_checkout_path = "sparse_trunk"

    parser = OptionParser(usage)
    parser.add_option("-r", "--repo_url", type="str", default=default_repo_url, dest="repo_url", help='Repository URL (default: "%s")' % default_repo_url)
    parser.add_option("-l", "--local_path", type="str", default=default_checkout_path, dest="local_path", help='Local checkout path (default: "%s")' % default_checkout_path)

    default_username = getpass.getuser()
    parser.add_option("-u", "--username", type="str", default=default_username, dest="svn_username", help='SVN login username (default: "%s")' % default_username)
    parser.add_option("-p", "--password", type="str", dest="svn_password", help="SVN login password")

    parser.add_option("-v", "--verbose", action="store_true", default=False, dest="verbose", help="Verbose output")
    (options, args) = parser.parse_args()

    client = getSvnClient(options)
    group_sparse_checkout(
        options,
        client,
        options.repo_url,
        map(os.path.relpath, args),
        options.local_path)

Oder führen Sie einen nicht rekursiven Checkout von /trunk durch und führen Sie dann einfach eine manuelle Aktualisierung der drei benötigten Verzeichnisse durch.

Wenn Sie bereits über die vollständige lokale Kopie verfügen, können Sie mithilfe von unerwünschte Unterordner entfernen --set-depth Befehl.

svn update --set-depth=exclude www

Sehen: http://blogs.collab.net/subversion/sparse-directories-now-with-exclusion

Der set-depth Der Befehl unterstützt mehrere Pfade.

Durch das Aktualisieren der lokalen Root-Kopie wird die Tiefe des geänderten Ordners nicht geändert.

Um den Ordner wieder so zu machen, dass er wieder recusiv ausgecheckt wird, können Sie Folgendes verwenden: --set-depth wieder mit unendlich param.

svn update --set-depth=infinity www

Irgendwie.Wie Bobby sagt:

svn co file:///.../trunk/foo file:///.../trunk/bar file:///.../trunk/hum

erhält die Ordner, aus Subversion-Sicht erhalten Sie jedoch separate Ordner.Sie müssen für jeden Unterordner separate Commits und Updates durchführen.

Ich glaube nicht, dass Sie einen Teilbaum auschecken und dann mit dem Teilbaum als einzelne Einheit arbeiten können.

Nicht besonders nützlich, nein.Sie können Teilbäume auschecken (wie in Bobby Jacks Vorschlag), aber dann verlieren Sie die Möglichkeit, sie atomar zu aktualisieren/festzuschreiben;Dazu müssen sie unter ihrem gemeinsamen übergeordneten Element platziert werden. Sobald Sie das gemeinsame übergeordnete Element auschecken, laden Sie alles unter diesem übergeordneten Element herunter.Nicht rekursiv ist keine gute Option, da Updates und Commits rekursiv sein sollen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top