using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.VisualStudio.SourceSafe.Interop;
using System.IO;
namespace DumpVssProjectStruc
{
public class VssReader
{
IVSSDatabase vssdb = new VSSDatabase();
DateTime? notAfter = null;
public VssReader(string ssdir, string ssuser, string sspwd)
{
vssdb.Open(ssdir, ssuser, sspwd);
}
//取得專案檔案結構XML,傳入saveFolder參數可將最後版本檔案存入指定目錄
//傳入notAfter則可選取某個時間之前簽入的檔案
public XDocument ReadProject(string path,
string saveFolder = null, DateTime? notAfter = null)
{
this.notAfter = notAfter;
XDocument xd = XDocument.Parse("<P />");
Explore(path, xd.Root, saveFolder);
return xd;
}
//以遞迴方式取得專案結構的所有檔案,若傳入savePath則會一併取得檔案寫入
public void Explore(string path, XElement container, string savePath = null)
{
VSSItem proj = vssdb.get_VSSItem(path, false);
//在XML建立目錄元素
XElement dir = new XElement("D",
new XAttribute("P", proj.Spec), new XAttribute("N", proj.Name));
if (!string.IsNullOrEmpty(savePath))
{
//若有指定儲存位置,計算路徑並確保資料夾已建立
savePath = Path.Combine(savePath, proj.Name);
if (!Directory.Exists(savePath))
Directory.CreateDirectory(savePath);
}
foreach (VSSItem item in proj.get_Items(false))
{
//若為VSSITEM_PROJECT,等同目錄,要再展開其下的子項目
if (item.Type == (int)VSSItemType.VSSITEM_PROJECT)
Explore(item.Spec, dir, savePath);
else
{
//在XML建立檔案項目元素
XElement file = new XElement("F",
new XAttribute("P", item.Spec),
new XAttribute("N", item.Name));
bool saved = false;
//取得該項目的所有版本資訊
foreach (VSSVersion v in item.Versions)
{
//若有指定簽入時間限制,忽略晚於限制時間的版本
if (notAfter != null & v.Date.CompareTo(notAfter) > 0)
continue;
//在檔案項目元素下新增版本元素
file.Add(new XElement("V",
new XAttribute("N", //若為標籤,則在前方加上l當作版號
string.IsNullOrEmpty(v.Label) ?
v.VersionNumber.ToString() : "l" + v.Label),
new XAttribute("U", v.Username),
new XAttribute("T",
v.Date.ToString("yyyy/MM/dd HH:mm:ss"))
));
//存入第一個吻合的版本(忽略標籤版本)
if (!string.IsNullOrEmpty(savePath) &&
string.IsNullOrEmpty(v.Label) && !saved)
{
string filePath = Path.Combine(savePath, item.Name);
v.VSSItem.Get(ref filePath, 0);
saved = true;
}
//若有簽入時間限制,則只包含吻合的第一筆
if (notAfter != null) break;
}
dir.Add(file);
}
}
container.Add(dir);
}
}
}