通常情况下,我会使用svn list -R .
查找我已检出的subversion存储库中的所有文件。
然而,对于像LLVM这样的大型回购,它只是太慢了。
$ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
... lots of files
U llvm
Checked out revision 262801.
$ cd llvm
$ time svn list -R . > files.txt
svn list -R . > files.txt 0.79s user 0.13s system 0% cpu 1:50.73 total
差不多两分钟!我可以使用find
做得更好(虽然我之后需要过滤掉.svn
):
$ time find . -type f > find_files.txt
find . -type f > find_files.txt 0.02s user 0.02s system 98% cpu 0.040 total
似乎subversion正在为repo中的所有20,000个文件发出网络请求!如果我删除了我的网络连接:
$ time svn list -R . > files_offline.txt
svn: E170013: Unable to connect to a repository at URL 'http://llvm.org/svn/llvm-project/llvm/trunk'
svn: E670002: Name or service not known
svn list -R . > files_offline.txt 0.02s user 0.01s system 41% cpu 0.056 total
我可以在不使用网络的情况下列出本地subversion结帐中的所有文件吗?
答案 0 :(得分:3)
UPD :如果您是Windows用户,可以从此处下载svncmd
工具:https://sf.net/p/svncmd/scripts/HEAD/tree/trunk(按钮Download snapshot
)。
请在此处查看svn_list.bat
脚本:https://sf.net/p/svncmd/scripts/HEAD/tree/trunk/Scripts/svn_list.bat
使用示例:
call svn_list.bat -offline branch/current > files.lst
call svn_list.bat -offline -wcroot branch/current branch/current/myproject > files.lst
SVN wc.db是sqlite数据库。您可以使用“Commandite Shell For SQLite”直接访问SVN数据库文件:https://www.sqlite.org/cli.html
例如,1.9.4数据库实现包含这些表:
表之间的差异在于对存储库上次提交的更改:
因此,如果您希望基本文件列表包含本地更改条目,则必须使用NODES_CURRENT表。如果您想要没有本地更改条目的基本文件列表,则必须使用NODES_BASE表。
以下是Windows批处理shell的用法示例:
sqlite3.exe -batch wc.db ".headers off" "select local_relpath from nodes_base where local_relpath != ''"
sqlite3.exe -batch wc.db ".headers off" "select local_relpath from nodes_current where local_relpath != ''"
sqlite3.exe -batch wc.db ".headers off" "select local_relpath from nodes_current where local_relpath != '' and presence = 'normal'"
提示强> 要查找wc.db文件,例如,通过F3键直接从Total Commander查找,您可以安装sqliteviewer插件。
<强> TIP2:强> 您必须在工作副本目录树(递归)的路上转储每个“.svn / wc.db”文件,以将所有文件列表作为“svn list -R”。确实
<强> TIP3:强> “svn list”转储NODES_BASE条目(第一个示例)。
<强> TIP4:强> “svn list”的输出与local_relpath字段的输出略有不同,因为:
-
如果要至少更正utf-8输出和尾部斜杠,例如,在Windows控制台中,您必须编写一组命令并使SQL请求复杂化:
chcp 65001
sqlite3.exe -batch wc.db ".headers off" "with new_nodes as ( select case when kind != 'dir' then local_relpath else local_relpath || '/' end as new_paths from nodes_base where local_relpath != '') select * from new_nodes order by new_paths asc"
输出将几乎关闭到“svn list”输出,除了带有'/','。'的行之间的错误顺序。和''角色在同一个位置。
答案 1 :(得分:1)
svn status -v
但是可以为您提供所需的信息 - 它需要一些预处理给定的输出。以下是C#的一些代码片段:
/// <summary>
/// Lists all files being under svn version control, recursively. Does not include directories.
///
/// Does not list newly added files (Which are not yet committed)
/// </summary>
/// <param name="path">Path where to take files</param>
/// <returns>List of files</returns>
static public List<String> svnGetFileList( String path, bool bRecursive = true)
{
// If you're online - this kind of line can be used.
//List<String> l = ExecCmd("svn ls \"" + path + "\" " + ((bRecursive) ? "--recursive" : "")).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
String svnStatusText = ExecCmd("svn status -v \"" + path + "\" ");
List<String> l = Regex.Matches(svnStatusText, "^[^?].{6} +[0-9]+ +[0-9]+ +(.*?) +([^\r\n]+)", RegexOptions.Multiline).Cast<Match>().Select(x => x.Groups[2].Value).ToList();
// [^?] - all versioned files only - status must not contain '?' - unversioned.
// skip 6 character columns (one character wide).
// skip 2 svn revisions
// skip svn login (.*) - non greedy match.
for (int i = 0; i < l.Count; i++)
{
if (l[i].Length <= path.Length) // Only for first entry (directory name)
{
l.RemoveAt(i);
i--;
continue;
}
if (Directory.Exists(l[i]))
{
l.RemoveAt(i);
i--;
continue;
}
l[i] = l[i].Substring(path.Length + 1); // Cut off main path.
if (!bRecursive && l[i].Contains("\\")) // Don't list sub-folders
{
l.RemoveAt(i);
i--;
continue;
}
}
return l;
}
/// <summary>
/// Executes command and throw exception if something unexpected happened.
/// </summary>
/// <param name="cmd">command to execute</param>
/// <returns>String logged from standard output and standard error</returns>
public static String ExecCmd(String cmd)
{
String error = "";
if (!ExecCmd(cmd, ref error))
{
throw new Exception(error);
}
return error;
} //ExecCmd
/// <summary>
/// Executes command and returns standard output & standard error to error string.
/// </summary>
/// <returns>true if error code was 0, false if something else</returns>
public static bool ExecCmd(String cmd, ref String error)
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
// Whole command should be quoted.
// cmd.exe /C ""mytool.exe" "c:\mypath\myfile.txt""
// ^ ^ ^
// https://social.msdn.microsoft.com/forums/vstudio/en-US/03ea84cf-19a6-450d-a3d6-8a139857e0cd/help-with-paths-containing-spaces
//
p.StartInfo.Arguments = "/C \"" + cmd + "\" 2>&1";
// Console.WriteLine("Executing 'cmd.exe " + p.StartInfo.Arguments + "'");
p.Start();
error = p.StandardOutput.ReadToEnd();
p.WaitForExit();
if (p.ExitCode != 0)
{
error += "\r\n (Executed command was: " + cmd + ")";
return false;
}
return true;
} //ExecCmd