private void ReadVersion(string version, List <ElementVersion> newVersions, Cleartool cleartool) { Match match = _versionRegex.Match(version); if (!match.Success) { Logger.TraceData(TraceEventType.Warning, (int)TraceId.ReadCleartool, "Could not parse '" + version + "' as a clearcase version"); return; } string elementName = match.Groups[1].Value; bool isDir; string oid; lock (cleartool) oid = cleartool.GetOid(elementName, out isDir); if (string.IsNullOrEmpty(oid)) { Logger.TraceData(TraceEventType.Warning, (int)TraceId.ReadCleartool, "Could not find oid for element " + elementName); return; } lock (_oidsToCheck) _oidsToCheck.Remove(oid); Element element; lock (ElementsByOid) if (!ElementsByOid.TryGetValue(oid, out element)) { element = new Element(elementName, isDir) { Oid = oid }; ElementsByOid.Add(oid, element); } else if (element.Name != elementName) { // the element is now seen with a different name in the currently used view Logger.TraceData(TraceEventType.Information, (int)TraceId.ReadCleartool, string.Format("element with oid {0} has a different name : now using {1} instead of {2}", oid, elementName, element.Name)); element.Name = elementName; } string[] versionPath = match.Groups[2].Value.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); string branchName = versionPath[versionPath.Length - 2]; int versionNumber = int.Parse(versionPath[versionPath.Length - 1]); // since we call ourself recursively to check the previous version, we first check the recursion end condition ElementBranch branch; if (element.Branches.TryGetValue(branchName, out branch) && branch.Versions.Count > 0 && branch.Versions.Last().VersionNumber >= versionNumber) { // already read return; } Logger.TraceData(TraceEventType.Start | TraceEventType.Verbose, (int)TraceId.ReadCleartool, "Start reading version", version); string previousVersion; lock (cleartool) previousVersion = cleartool.GetPredecessor(version); int previousVersionNumber = -1; if (previousVersion == null) { if (branchName != "main" || versionNumber != 0) { throw new Exception("Failed to retrieve predecessor of " + version); } branch = new ElementBranch(element, branchName, null); element.Branches[branchName] = branch; } else { ReadVersion(elementName + "@@" + previousVersion, newVersions, cleartool); string[] parts = previousVersion.Split('\\'); previousVersionNumber = int.Parse(parts[parts.Length - 1]); } if (!element.Branches.TryGetValue(branchName, out branch)) { if (versionNumber != 0) { // we should have completed in ReadVersion(elementName + "@@" + previousVersion) throw new Exception("Could not complete branch " + branchName); } ElementVersion branchingPoint = null; if (versionPath.Length > 2) { string parentBranchName = versionPath[versionPath.Length - 3]; ElementBranch parentBranch; if (!element.Branches.TryGetValue(parentBranchName, out parentBranch) || (branchingPoint = parentBranch.Versions.FirstOrDefault(v => v.VersionNumber == previousVersionNumber)) == null) { throw new Exception("Could not complete branch " + parentBranchName); } } branch = new ElementBranch(element, branchName, branchingPoint); element.Branches[branchName] = branch; } bool added = AddVersionToBranch(branch, versionNumber, isDir, newVersions, cleartool); if (!added && branch.Versions.Count == 0) { // do not leave an empty branch element.Branches.Remove(branchName); } Logger.TraceData(TraceEventType.Stop | TraceEventType.Verbose, (int)TraceId.ReadCleartool, "Stop reading version", version); }
private bool AddVersionToBranch(ElementBranch branch, int versionNumber, bool isDir, List <ElementVersion> newVersions, Cleartool cleartool) { ElementVersion version; if (isDir) { var dirVersion = new DirectoryVersion(branch, versionNumber); Dictionary <string, string> res; lock (cleartool) res = cleartool.Ls(dirVersion.ToString()); foreach (var child in res) { lock (ElementsByOid) { Element childElement; if (ElementsByOid.TryGetValue(child.Value, out childElement)) { dirVersion.Content.Add(new KeyValuePair <string, Element>(child.Key, childElement)); } else if (child.Value.StartsWith(SymLinkElement.SYMLINK)) { Element symLink = new SymLinkElement(branch.Element, child.Value); Element existing; if (ElementsByOid.TryGetValue(symLink.Oid, out existing)) { symLink = existing; } else { ElementsByOid.Add(symLink.Oid, symLink); } dirVersion.Content.Add(new KeyValuePair <string, Element>(child.Key, symLink)); } else { _contentFixups.Add(new Tuple <DirectoryVersion, string, string>(dirVersion, child.Key, child.Value)); } } } version = dirVersion; } else { version = new ElementVersion(branch, versionNumber); } List <Tuple <string, int> > mergesTo, mergesFrom; lock (cleartool) cleartool.GetVersionDetails(version, out mergesTo, out mergesFrom); if (mergesTo != null) { foreach (var merge in mergesTo) { // only merges between branches are interesting if (merge.Item1 != branch.BranchName) { lock (_mergeFixups) _mergeFixups.Add(new Tuple <ElementVersion, string, int, bool>(version, merge.Item1, merge.Item2, true)); } } } if (mergesFrom != null) { foreach (var merge in mergesFrom) { // only merges between branches are interesting if (merge.Item1 != branch.BranchName) { lock (_mergeFixups) _mergeFixups.Add(new Tuple <ElementVersion, string, int, bool>(version, merge.Item1, merge.Item2, false)); } } } if (version.Date > _originDate) { Logger.TraceData(TraceEventType.Information, (int)TraceId.ReadCleartool, string.Format("Skipping version {0} : {1} > {2}", version, version.Date, _originDate)); return(false); } branch.Versions.Add(version); if (newVersions != null) { newVersions.Add(version); } return(true); }