/// <summary> /// Finds objects of the same name, but different hashes /// </summary> private static void FindModifieds(ChangelogBuilder changelog, string prefix, VDKeyedCollection byName, VDKeyedCollection otherByName) { var toRemove = new LinkedList <string>(); foreach (var otherVD in otherByName) { //if (byName.ContainsKey(pair.Key)) if (byName.Contains(otherVD.Filename)) { VersionData thisVD = byName[otherVD.Filename]; if (otherVD.Filetype == thisVD.Filetype) { string fpath = PrefixFilename(prefix, otherVD.Filename); changelog.Modify(fpath, otherVD.Hash); if (otherVD.Filetype == FileType.Directory) { var subchangelog = BuildChangelog(thisVD, otherVD, fpath); changelog.Aggregate(subchangelog); } toRemove.AddLast(otherVD.Filename); } } } foreach (string s in toRemove) { byName.Remove(s); otherByName.Remove(s); } }
/// <summary> /// Adds all descendant files of a Directory to a changelog /// </summary> private static void AggregateAdd(ChangelogBuilder changelog, string prefix, VersionData update) { foreach (var child in update.Children) { string fpath = PrefixFilename(prefix, child.Filename); changelog.Add(fpath, child.Hash); if (child.Filetype == FileType.Directory) { var subchangelog = BuildChangelog(child, null, fpath); changelog.Aggregate(subchangelog); } } }
/// <summary> /// Adds a VersionData to the tree in its specified path /// </summary> /// <param name="path"></param> /// <param name="vdata"></param> public void AddVersionData(string path, VersionData vdata) { string[] directoryPath = VersionDataPath.SplitDirectories(path); DataNode node = GetParentNode(directoryPath); string filename = directoryPath[directoryPath.Length - 1]; if (node.children.Contains(filename)) { node.children[filename].data = vdata; } else { node.children.Add(new DataNode(vdata)); } }
/// <summary> /// Adds all the descendants of vdata to root /// </summary> /// <param name="vdata"></param> /// <param name="node"></param> private void AddDataDirectory(VersionData vdata, DataNode node) { if (vdata.Filetype != VersionData.FileType.Directory) { throw new ArgumentException("vdata must be of type Directory"); } foreach (var child in vdata.Children) { DataNode cnode = new DataNode(child); node.children.Add(cnode); if (child.Filetype == VersionData.FileType.Directory) { AddDataDirectory(child, cnode); } } }
/// <summary> /// Recursively builds a Changelog by comparing each directory to its analogue and finding differences /// </summary> /// <param name="original"></param> /// <param name="update"></param> /// <param name="prefix"></param> /// <returns></returns> public static ChangelogBuilder BuildChangelog(VersionData original, VersionData update, string prefix = "") { ChangelogBuilder changelog = new ChangelogBuilder(); var byHash = new Dictionary <string, LinkedList <string> >(); var otherByHash = new Dictionary <string, LinkedList <string> >(); var byName = new VDKeyedCollection(); var otherByName = new VDKeyedCollection(); if (original == null) { if (update == null) { throw new ArgumentNullException("original and update"); } } else if (original.filetype == FileType.File) { throw new InvalidOperationException("Cannot call GetChangelog on a FileType.File type"); } if (update != null && update.filetype == FileType.File) { throw new ArgumentException("child must be of type FileType.File"); } if (update == null) { AggregateRemove(changelog, prefix, original); return(changelog); } if (original == null) { AggregateAdd(changelog, prefix, update); return(changelog); } AddAlteredFiles(original.children, update.children, byName, byHash); AddAlteredFiles(update.children, original.children, otherByName, otherByHash); FindRenames(changelog, prefix, byName, otherByName, byHash, otherByHash); FindModifieds(changelog, prefix, byName, otherByName); FindAddRemoveds(changelog, prefix, byName, otherByName); return(changelog); }
public DataNode(VersionData data) { children = new GenericKeyedCollection <string, DataNode>(node => node.filename); this.data = data; filename = data.Filename; }
/// <summary> /// Computes the Changelog between this and its descendant Version, such that "this + changelog => child" /// </summary> /// <param name="child"></param> /// <returns></returns> public Changelog GetChangelog(Version child) { return(VersionData.BuildChangelog(Data, child.Data).GetChangelog()); }
public Version(VersionData data) { this.data = data; this.hash = GetHash(); }
public Version(VersionData data, string hash) { this.data = data; this.hash = hash; }
/// <summary> /// Removes all descendant files of a Directory to a changelog /// </summary> private static void AggregateRemove(ChangelogBuilder changelog, string prefix, VersionData original) { foreach (var child in original.Children) { string fpath = PrefixFilename(prefix, child.Filename); changelog.Remove(fpath); if (child.Filetype == FileType.Directory) { var subchangelog = BuildChangelog(child, null, fpath); changelog.Aggregate(subchangelog); } } }