private void WriteChangeSet(ChangeSet changeSet, Dictionary <string, List <ChangeSet> > branches, Dictionary <string, LabelInfo> labels, Dictionary <string, LabelMeta> labelMetas) { if (changeSet.IsEmpty) { Logger.TraceData(TraceEventType.Information, (int)TraceId.ApplyChangeSet, "Skipped empty ChangeSet " + changeSet); return; } bool writeCommit = true; if (changeSet.IsEmptyGitCommit) { Logger.TraceData(TraceEventType.Information, (int)TraceId.ApplyChangeSet, "Only writing the tags (if any) for " + changeSet); writeCommit = false; } string branchName = changeSet.Branch == "main" ? "master" : MaybeRenamed(changeSet.Branch); if (writeCommit) { _writer.Write("commit refs/heads/" + branchName + "\n"); _writer.Write("mark :" + changeSet.Id + "\n"); _writer.Write("committer " + changeSet.AuthorName + " <" + changeSet.AuthorLogin + "> " + (changeSet.StartTime - _epoch).TotalSeconds + " +0200\n"); _writer.Write("# " + changeSet.StartTime + "\n"); InlineString(changeSet.GetComment()); if (changeSet.BranchingPoint != null) { _writer.Write("from :" + changeSet.BranchingPoint.Id + "\n"); _startedBranches.Add(branchName); } else if (_isIncremental && !_startedBranches.Contains(branchName)) { _writer.Write("from refs/heads/" + branchName + "^0\n"); _startedBranches.Add(branchName); } foreach (var merge in changeSet.Merges) { _writer.Write("merge :" + merge.Id + "\n"); } if (!_initialFilesAdded && branchName == "master") { _initialFilesAdded = true; foreach (var initialFile in InitialFiles) { var fileInfo = new FileInfo(initialFile.Item2); if (fileInfo.Exists) { _writer.Write("M 644 inline " + initialFile.Item1 + "\n"); InlineString(File.ReadAllText(initialFile.Item2)); } } } // order is significant : we must Rename and Copy files before (maybe) deleting their directory foreach (var pair in changeSet.Renamed) { _writer.Write("R \"" + RemoveDotRoot(pair.Item1) + "\" \"" + RemoveDotRoot(pair.Item2) + "\"\n"); } foreach (var pair in changeSet.Copied) { _writer.Write("C \"" + RemoveDotRoot(pair.Item1) + "\" \"" + RemoveDotRoot(pair.Item2) + "\"\n"); } foreach (var removed in changeSet.Removed) { _writer.Write("D " + RemoveDotRoot(removed) + "\n"); } foreach (var symLink in changeSet.SymLinks) { _writer.Write("M 120000 inline " + RemoveDotRoot(symLink.Item1) + "\n"); InlineString(RemoveDotRoot(symLink.Item2)); } foreach (var namedVersion in changeSet.Versions) { if (namedVersion.Version is DirectoryVersion || namedVersion.Names.Count == 0) { continue; } bool isEmptyFile = namedVersion.Version.VersionNumber == 0 && namedVersion.Version.Branch.BranchName == "main"; if (_doNotIncludeFileContent || isEmptyFile) { foreach (string name in namedVersion.Names.Select(RemoveDotRoot)) { if (isEmptyFile) { _writer.Write("M 644 inline " + name + "\ndata 0\n\n"); } else { // don't use InlineString here, so that /FetchFileContent is easy to implement _writer.Write("M 644 inline " + name + "\ndata <<EOF\n" + namedVersion.Version + "#" + namedVersion.Version.Element.Oid + "\nEOF\n\n"); // also include name in a comment for hooks in /FetchFileContent _writer.Write("#" + name + "\n"); } } continue; } InlineClearcaseFileVersion(namedVersion.Version.Element.Name, namedVersion.Version.Element.Oid, namedVersion.Version.VersionPath, namedVersion.Names.Select(RemoveDotRoot), true); } } foreach (var label in changeSet.Labels) { _writer.Write("tag " + label + "\n"); _writer.Write("from :" + changeSet.Id + "\n"); LabelMeta meta = labelMetas[label]; var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); _writer.Write("tagger " + meta.AuthorName + " <" + meta.AuthorLogin + "> " + (meta.Created - epoch).TotalSeconds + " +0000\n"); // var +0200 List <Tuple <ElementVersion, ElementVersion> > possibleBroken = labels[label].PossiblyBroken.Where( t => null != RelativeRoots.Find( r => RemoveDotRoot(t.Item1.ToString().Replace("\\", "/") + "/").StartsWith(r + "/") )).ToList(); if (possibleBroken.Count > 0) { Logger.TraceData(TraceEventType.Warning, (int)TraceId.ApplyChangeSet, "Label " + label + " was inconsistent when writing it. Count", possibleBroken.Count); string msg = "Warning! This tag could be incorrect.\nGot an unexpected result, though it could still be correct.\n\n"; foreach (Tuple <ElementVersion, ElementVersion> items in possibleBroken) { msg += "Expected \"" + RemoveDotRoot(items.Item1.ToString()) + "\", but got " + (items.Item2 == null ? "nothing" : "\"" + RemoveDotRoot(items.Item2.ToString()) + "\"") + ".\n"; } InlineString(msg); } else { _writer.Write("data 0\n\n"); } } }