Subversion存储库布局 [英] Subversion Repository Layout
问题描述
大多数Subversion工具都会使用/trunk,/branches和/tags创建默认的存储库布局.该文档还建议不要为每个项目使用单独的存储库,以便可以更轻松地共享代码.
Most subversion tools create a default repository layout with /trunk, /branches and /tags. The documentation also recommends not using separate repositories for each project, so that code can be more easily shared.
遵循该建议,使我拥有了一个具有以下布局的存储库:
Following that advice has led to me having a repository with the following layout:
/trunk
/Project1
/Project2
/branches
/Project1
/Project2
/tags
/Project1
/Project2
,依此类推,您就明白了.随着时间的流逝,我发现这种结构有些笨拙,并且我发现对建议的替代解释是这样的,例如:
and so on, you get the idea. Over time, I've found this structure a bit clumsy and it occurred to me that there's an alternative interpretation of the recommendations, such as:
/Project1
/trunk
/branches
/tags
/Project2
/trunk
/branches
/tags
那么,人们使用哪种布局,为什么?或者-还有另一种方法可以做我完全错过的事情吗?
So, which layout do people use, and why? Or - is there another way to do things that I've completely missed?
推荐答案
我决定硬着头皮重新整理我的存储库.我写了一个小程序来帮助(下).我遵循的步骤是:
I decided to bite the bullet and restructure my repository. I wrote a small program to assist (below). The steps I followed were:
- 制作原始存储库的备份副本.
-
svn checkout
整个存储库.这花费了很长时间,并且占用了大量磁盘空间. - 在上一步的工作副本上从下面运行程序.
- 检查修改后的工作副本并整理所有遗留的问题(例如
svn delete
过时的 trunk , tags 和 branches 文件夹) -
svn commit
回到存储库.
- Make a backup copy of the original repository.
svn checkout
the entire repository. This took a long time and a lot of disk space.- Run the program from below on the working copy from the previous step.
- Examine the modified working copy and tidy up any left over issues (eg.
svn delete
the obsolete trunk, tags and branches folders) svn commit
back to the repository.
整个过程耗时,但是我决定采用这种方法,因为修改工作副本比黑客入侵实时存储库要安全得多,而且我可以选择在所有工作副本出错的情况下简单地丢弃工作副本.修复工作副本中的任何问题,并将整个重组作为一个修订提交.
This whole process took time, but I decided to take this approach because modifying a working copy is a lot safer than hacking up a live repository and I had the options to simply throw away the working copy if it all went wrong, to fix any issue in the working copy and commit the entire restructure as a single revision.
这是我用来移动的C#代码.需要SharpSvn库.
Here's the C# code I used to do the moving. Requires SharpSvn library.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using SharpSvn;
/**
*
* Program operation:
* 1. Parse command line to determine path to working copy root
* 2. Enumerate folders in the /trunk
* 3. Restructure each project folder in /trunk
*
*
* Restructure a Project:
* 1. Get the project name (folder name in /trunk/{Project})
* 2. SVN Move /trunk/{Project} to /{Project}/trunk
* 3. Reparent Project, branches
* 4. Reparent Project, tags
*
* Reparent(project, folder)
* If /{folder}/{Project} exists
* SVN Move /{folder}/{Project} to /{Project}/{Folder}
* else
* Create folder /{Project}/{Folder}
* SVN Add /{Project}/{Folder}
*
**/
namespace TiGra.SvnRestructure
{
/// <summary>
/// Restructures a Subversion repository from
/// /trunk|branches|tags/Project
/// to
/// /Project/trunk|branches|tags
/// </summary>
internal class Program
{
private static string WorkingCopy;
private static string SvnUri;
private static string Branches;
private static string Tags;
private static string Trunk;
private static SvnClient svn;
private static List<string> Projects;
private static void Main(string[] args)
{
ProcessCommandLine(args);
CreateSvnClient();
EnumerateProjectsInTrunk();
RestructureProjects();
Console.ReadLine();
}
private static void RestructureProjects()
{
foreach (var project in Projects)
{
RestructureSingleProject(project);
}
}
private static void RestructureSingleProject(string projectPath)
{
var projectName = Path.GetFileName(projectPath);
var projectNewRoot = Path.Combine(WorkingCopy, projectName);
bool hasBranches = Directory.Exists(Path.Combine(Branches, projectName));
bool hasTags = Directory.Exists(Path.Combine(Tags, projectName));
Reparent(Path.Combine(Trunk, projectName), Path.Combine(projectNewRoot, "trunk"));
if (hasBranches)
Reparent(Path.Combine(Branches, projectName), Path.Combine(projectNewRoot, "branches"));
if (hasTags)
Reparent(Path.Combine(Tags, projectName), Path.Combine(projectNewRoot, "tags"));
}
private static void Reparent(string oldPath, string newPath)
{
Console.WriteLine(string.Format("Moving {0} --> {1}", oldPath, newPath));
svn.Move(oldPath, newPath, new SvnMoveArgs(){CreateParents = true});
}
private static void EnumerateProjectsInTrunk()
{
var list = EnumerateFolders("trunk");
Projects = list;
}
/// <summary>
/// Enumerates the folders in the specified subdirectory.
/// </summary>
/// <param name="trunk">The trunk.</param>
private static List<string> EnumerateFolders(string root)
{
var fullPath = Path.Combine(WorkingCopy, root);
var folders = Directory.GetDirectories(fullPath, "*.*", SearchOption.TopDirectoryOnly).ToList();
folders.RemoveAll(s => s.EndsWith(".svn")); // Remove special metadata folders.
return folders;
}
private static void CreateSvnClient()
{
svn = new SharpSvn.SvnClient();
}
/// <summary>
/// Processes the command line. There should be exactly one argument,
/// which is the path to the working copy.
/// </summary>
private static void ProcessCommandLine(string[] args)
{
if (args.Length != 1)
throw new ArgumentException("There must be exactly one argument");
var path = args[0];
if (!Directory.Exists(path))
throw new ArgumentException("The specified working copy root could not be found.");
WorkingCopy = path;
Branches = Path.Combine(WorkingCopy, "branches");
Tags = Path.Combine(WorkingCopy, "tags");
Trunk = Path.Combine(WorkingCopy, "trunk");
}
}
}
这篇关于Subversion存储库布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!