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, eine Subversion-Prüfung mit nur diesen 3 Verzeichnissen unter Trunk durchzuführen?
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, eine Subversion-Prüfung mit nur diesen 3 Verzeichnissen unter Trunk durchzuführen?
Antworten:
Subversion 1.5 führt spärliche Kassen ein, die möglicherweise nützlich sind. Aus der Dokumentation :
... spärliche Verzeichnisse (oder flache Kassen ) ... ermöglichen das einfache Auschecken einer Arbeitskopie - oder eines Teils einer Arbeitskopie - flacher als die vollständige Rekursion, wobei Sie zuvor ignorierte Dateien und Unterverzeichnisse in a einfügen können späteren Zeitpunkt.
Dank der Kommentare zu meinem Beitrag hier sieht es tatsächlich so aus, als wären spärliche Verzeichnisse der richtige Weg. Ich glaube, das 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
Alternativ --depth immediates
statt empty
checkt Dateien und Verzeichnisse in trunk/proj
ohne deren Inhalte. 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 eine nicht rekursive Prüfung durchführen. Dies ist ein älterer und weniger flexibler Weg, 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
Skipped 'prom/foo'
nach svn update --set-depth infinity proj/foo
:(
svn update --set-depth immediates proj
, damit proj / foo für die Aktualisierung erstellt wird.
Ich habe ein Skript geschrieben, um komplexe, spärliche Kassen 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)
Wenn Sie bereits über die vollständige lokale Kopie verfügen, können Sie unerwünschte Unterordner mithilfe des --set-depth
Befehls entfernen .
svn update --set-depth=exclude www
Siehe: http://blogs.collab.net/subversion/sparse-directories-now-with-exclusion
Der set-depth
Befehl unterstützt Multipile-Pfade.
Durch das Aktualisieren der lokalen Stammkopie wird die Tiefe des geänderten Ordners nicht geändert.
Sie können den Ordner mit dem Parameter --set-depth
infinity erneut verwenden, um das rekusive Auschecken des Ordners wiederherzustellen.
svn update --set-depth=infinity www
Art von. Wie Bobby sagt:
svn co file:///.../trunk/foo file:///.../trunk/bar file:///.../trunk/hum
wird die Ordner erhalten, aber Sie werden separate Ordner aus einer Subversion-Perspektive erhalten. 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 eine 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 Fähigkeit, sie atomar zu aktualisieren / festzuschreiben. Dazu müssen sie unter ihrem gemeinsamen Elternteil platziert werden. Sobald Sie das gemeinsame Elternteil auschecken, laden Sie alles unter diesem gemeinsamen Elternteil herunter. Nicht rekursiv ist keine gute Option, da Updates und Commits rekursiv sein sollen.