private FolderMetaData GetMetadataForUpdate(IHttpRequest request, UpdateReportData updatereport, TFSSourceControlProvider sourceControlProvider, out int targetRevision) { string basePath = PathParser.GetLocalPath(request, updatereport.SrcPath); FolderMetaData metadata; if (updatereport.TargetRevision != null) { targetRevision = int.Parse(updatereport.TargetRevision); } else { targetRevision = sourceControlProvider.GetLatestVersion(); } if (updatereport.IsCheckOut) { metadata = (FolderMetaData)sourceControlProvider.GetItemsWithoutProperties(targetRevision, basePath, Recursion.Full); } else { metadata = sourceControlProvider.GetChangedItems(basePath, int.Parse(updatereport.Entries[0].Rev), targetRevision, updatereport); } if (metadata != null) { loader = new AsyncItemLoader(metadata, sourceControlProvider); ThreadPool.QueueUserWorkItem(state => loader.Start()); } return(metadata); }
private bool IsMissing(UpdateReportData data, string localPath, string name) { if (data.Missing == null || data.Missing.Count == 0) { return(false); } string path = localPath.Substring(1); if (path.EndsWith("/") == false) { path += "/"; } if (name.StartsWith(path)) { name = name.Substring(path.Length); } if (data.Missing.Contains(name)) { return(true); } foreach (string missing in data.Missing) { if (name.StartsWith(missing))// the missing is the parent of this item { return(true); } } return(false); }
private void ReplayReport(IHttpRequest request, IHttpResponse response, TFSSourceControlProvider sourceControlProvider, ReplayReportData replayReport) { if (replayReport.Revision == 0) { response.StatusCode = (int)HttpStatusCode.OK; using (var output = new StreamWriter(response.OutputStream)) { output.Write( @"<?xml version=""1.0"" encoding=""utf-8""?> <S:editor-report xmlns:S=""svn:""> <S:target-revision rev=""0""/> </S:editor-report>"); return; } } var data = new UpdateReportData(); data.SrcPath = request.Url.AbsoluteUri; data.Entries = new List <EntryData>(); var item = new EntryData(); string localPath = PathParser.GetLocalPath(request); LogItem log = sourceControlProvider.GetLog(localPath, 0, sourceControlProvider.GetLatestVersion(), Recursion.None, 1); if (log.History.Length == 0) { WriteFileNotFoundResponse(request, response); } item.Rev = (replayReport.Revision - 1).ToString(); data.TargetRevision = (replayReport.Revision).ToString(); data.Entries.Add(item); SetResponseSettings(response, "text/xml; charset=\"utf-8\"", Encoding.UTF8, 200); response.SendChunked = true; using (var output = new StreamWriter(response.OutputStream)) { try { output.Write(@"<?xml version=""1.0"" encoding=""utf-8""?> <S:editor-report xmlns:S=""svn:"">"); int targetRevision; FolderMetaData metadata = GetMetadataForUpdate(request, data, sourceControlProvider, out targetRevision); output.WriteLine("<S:target-revision rev=\"{0}\"/>", targetRevision); OutputEditorReport(sourceControlProvider, metadata, replayReport.Revision, localPath == "/", output); output.Write("</S:editor-report>"); } catch (FileNotFoundException) { WriteFileNotFoundResponse(request, response); } } }
private string GetSrcPath(UpdateReportData updateReportRequest) { string url = handler.GetLocalPathFromUrl(updateReportRequest.SrcPath); if (updateReportRequest.UpdateTarget != null) { return(url + "/" + updateReportRequest.UpdateTarget); } return(url); }
private void UpdateReport(TFSSourceControlProvider sourceControlProvider, UpdateReportData updatereport, StreamWriter output, FolderMetaData metadata, int targetRevision) { output.Write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); output.Write("<S:update-report xmlns:S=\"svn:\" xmlns:V=\"http://subversion.tigris.org/xmlns/dav/\" xmlns:D=\"DAV:\" send-all=\"true\">\n"); output.Write("<S:target-revision rev=\"" + targetRevision + "\"/>\n"); UpdateReportService updateReportService = new UpdateReportService(this, sourceControlProvider); updateReportService.ProcessUpdateReportForDirectory(updatereport, metadata, output, true, false); output.Write("</S:update-report>\n"); }
private bool ItemExistsAtTheClient(ItemMetaData item, UpdateReportData updateReportRequest, string srcPath, int clientRevisionForItem) { if (sourceControlProvider != null) { return(updateReportRequest.IsCheckOut == false && IsMissing(updateReportRequest, srcPath, item.Name) == false && // we need to check both name and id to ensure that the item was not renamed sourceControlProvider.ItemExists(item.Name, clientRevisionForItem) && sourceControlProvider.ItemExists(item.Id, clientRevisionForItem)); } else { return(false); } }
private bool ShouldDeleteItemBeforeSendingToClient(ItemMetaData folder, UpdateReportData updateReportRequest, string srcPath, int clientRevisionForItem, bool existingFolder) { if (sourceControlProvider != null) { return(existingFolder == false && updateReportRequest.IsCheckOut == false && IsMissing(updateReportRequest, srcPath, folder.Name) == false && sourceControlProvider.ItemExists(folder.Name, clientRevisionForItem)); } else { return(existingFolder == false && updateReportRequest.IsCheckOut == false && IsMissing(updateReportRequest, srcPath, folder.Name) == false); } }
private static Dictionary <string, int> GetClientExistingFiles(string path, UpdateReportData reportData) { Dictionary <string, int> clientExistingFiles = new Dictionary <string, int>(); if (reportData.Entries != null) { foreach (EntryData entryData in reportData.Entries) { if (string.IsNullOrEmpty(path)) { clientExistingFiles["/" + entryData.path] = int.Parse(entryData.Rev); } else { clientExistingFiles["/" + path + "/" + entryData.path] = int.Parse(entryData.Rev); } } } return(clientExistingFiles); }
private static Dictionary <string, string> GetClientDeletedFiles(string path, UpdateReportData reportData) { Dictionary <string, string> clientDeletedFiles = new Dictionary <string, string>(); if (reportData.Missing != null) { foreach (string missingPath in reportData.Missing) { if (string.IsNullOrEmpty(path)) { clientDeletedFiles["/" + missingPath] = missingPath; } else { clientDeletedFiles["/" + path + "/" + missingPath] = missingPath; } } } return(clientDeletedFiles); }
public void CalculateDiff(string checkoutRootPath, int versionTo, int versionFrom, FolderMetaData checkoutRoot, UpdateReportData updateReportData) { clientExistingFiles = GetClientExistingFiles(checkoutRootPath, updateReportData); clientMissingFiles = GetClientDeletedFiles(checkoutRootPath, updateReportData); string projectRootPath = GetProjectRoot(checkoutRootPath); if (updateReportData.Entries != null) { foreach (EntryData data in updateReportData.Entries) { int itemVersionFrom = int.Parse(data.Rev); if (itemVersionFrom < versionFrom) { string rootPath = checkoutRootPath; if (updateReportData.UpdateTarget != null) { rootPath += "/" + updateReportData.UpdateTarget; } string targetPath = rootPath + "/" + data.path; if (targetPath.StartsWith("/")) { targetPath = targetPath.Substring(1); } CalculateChangeBetweenVersions(projectRootPath, targetPath, itemVersionFrom, checkoutRoot, itemVersionFrom, versionFrom); } } } if (versionFrom != versionTo) { // we have to calculate the difference from the project root // this is because we may have a file move from below the checkoutRootPath, // which we still need to consider FolderMetaData projectRoot = checkoutRoot; if (projectRootPath != checkoutRootPath) { projectRoot = (FolderMetaData)sourceControlProvider.GetItems(versionTo, projectRootPath, Recursion.None); string path = checkoutRootPath.Substring(0, checkoutRootPath.LastIndexOf('/')); path = path.Substring(path.IndexOf('/') + 1); FolderMetaData result = (FolderMetaData)FindItemOrCreateItem(projectRoot, projectRootPath, path, versionTo, Recursion.None); result.Items.Add(checkoutRoot); } CalculateChangeBetweenVersions(projectRootPath, -1, projectRoot, versionFrom, versionTo); } foreach (string missingItem in clientMissingFiles.Values) { if (sourceControlProvider.ItemExists(checkoutRootPath + "/" + missingItem, versionTo)) { FindItemOrCreateItem(checkoutRoot, checkoutRootPath, missingItem, versionTo, Recursion.Full); } } FlattenDeletedFolders(checkoutRoot); RemoveMissingItemsWhichAreChildrenOfRenamedItem(checkoutRoot); VerifyNoMissingItemMetaDataRemained(checkoutRoot); }
public void ProcessUpdateReportForFile(UpdateReportData updateReportRequest, ItemMetaData item, StreamWriter output, bool parentFolderWasDeleted) { if (item is DeleteMetaData) { if (!parentFolderWasDeleted) { output.Write("<S:delete-entry name=\"" + Helper.EncodeB(GetFileName(item.Name)) + "\"/>\n"); } } else { bool existingFile = false; string srcPath = GetSrcPath(updateReportRequest); int clientRevisionForItem = GetClientRevisionFor(updateReportRequest.Entries, StripBasePath(item, srcPath)); if (ItemExistsAtTheClient(item, updateReportRequest, srcPath, clientRevisionForItem)) { existingFile = true; } //another item with the same name already exists, need to remove it. if (!parentFolderWasDeleted && ShouldDeleteItemBeforeSendingToClient(item, updateReportRequest, srcPath, clientRevisionForItem, existingFile)) { output.Write("<S:delete-entry name=\"" + Helper.EncodeB(GetFileName(item.Name)) + "\"/>\n"); } if (existingFile) { output.Write("<S:open-file name=\"" + Helper.EncodeB(GetFileName(item.Name)) + "\" rev=\"" + clientRevisionForItem + "\">\n"); } else { output.Write("<S:add-file name=\"" + Helper.EncodeB(GetFileName(item.Name)) + "\">\n"); } string localPath = handler.GetLocalPath("/!svn/ver/" + item.Revision + "/" + Helper.Encode(item.Name, true)); output.Write("<D:checked-in><D:href>" + localPath + "</D:href></D:checked-in>\n"); output.Write("<S:set-prop name=\"svn:entry:committed-rev\">" + item.Revision + "</S:set-prop>\n"); output.Write("<S:set-prop name=\"svn:entry:committed-date\">" + Helper.FormatDate(item.LastModifiedDate) + "</S:set-prop>\n"); output.Write("<S:set-prop name=\"svn:entry:last-author\">" + item.Author + "</S:set-prop>\n"); if (sourceControlProvider == null) { output.Write("<S:set-prop name=\"svn:entry:uuid\">" + new Guid() + "</S:set-prop>\n"); } else { output.Write("<S:set-prop name=\"svn:entry:uuid\">" + sourceControlProvider.GetRepositoryUuid() + "</S:set-prop>\n"); } foreach (KeyValuePair <string, string> property in item.Properties) { output.Write("<S:set-prop name=\"" + property.Key + "\">" + property.Value + "</S:set-prop>\n"); } while (item.DataLoaded == false) // <== Uha { Thread.Sleep(100); } output.Write("<S:txdelta>"); output.Write(item.Base64DiffData); output.Write("\n</S:txdelta>"); output.Write("<S:prop><V:md5-checksum>" + item.Md5Hash + "</V:md5-checksum></S:prop>\n"); // Release data memory item.DataLoaded = false; item.Base64DiffData = null; if (existingFile) { output.Write("</S:open-file>\n"); } else { output.Write("</S:add-file>\n"); } } }
public void ProcessUpdateReportForDirectory(UpdateReportData updateReportRequest, FolderMetaData folder, StreamWriter output, bool rootFolder, bool parentFolderWasDeleted) { if (folder is DeleteFolderMetaData) { if (!parentFolderWasDeleted) { output.Write("<S:delete-entry name=\"" + Helper.EncodeB(GetFileName(folder.Name)) + "\"/>\n"); } } else { bool existingFolder = false; bool folderWasDeleted = parentFolderWasDeleted; if (rootFolder) { output.Write("<S:open-directory rev=\"" + updateReportRequest.Entries[0].Rev + "\">\n"); } else { string srcPath = GetSrcPath(updateReportRequest); int clientRevisionForItem = GetClientRevisionFor(updateReportRequest.Entries, StripBasePath(folder, srcPath)); if (ItemExistsAtTheClient(folder, updateReportRequest, srcPath, clientRevisionForItem)) { existingFolder = true; } //another item with the same name already exists, need to remove it. if (!parentFolderWasDeleted && ShouldDeleteItemBeforeSendingToClient(folder, updateReportRequest, srcPath, clientRevisionForItem, existingFolder)) { output.Write("<S:delete-entry name=\"" + Helper.EncodeB(GetFileName(folder.Name)) + "\"/>\n"); folderWasDeleted = true; } if (existingFolder) { output.Write("<S:open-directory name=\"" + Helper.EncodeB(GetFileName(folder.Name)) + "\" rev=\"" + updateReportRequest.Entries[0].Rev + "\">\n"); } else { output.Write("<S:add-directory name=\"" + Helper.EncodeB(GetFileName(folder.Name)) + "\" bc-url=\"" + handler.GetLocalPath("/!svn/bc/" + folder.Revision + "/" + Helper.Encode(folder.Name, true)) + "\">\n"); } } if (!rootFolder || updateReportRequest.UpdateTarget == null) { string svnVer = handler.GetLocalPath("/!svn/ver/" + folder.Revision + "/" + Helper.Encode(folder.Name, true)); output.Write("<D:checked-in><D:href>" + svnVer + "</D:href></D:checked-in>\n"); output.Write("<S:set-prop name=\"svn:entry:committed-rev\">" + folder.Revision + "</S:set-prop>\n"); output.Write("<S:set-prop name=\"svn:entry:committed-date\">" + Helper.FormatDate(folder.LastModifiedDate) + "</S:set-prop>\n"); output.Write("<S:set-prop name=\"svn:entry:last-author\">" + folder.Author + "</S:set-prop>\n"); if (sourceControlProvider == null) { output.Write("<S:set-prop name=\"svn:entry:uuid\">" + new Guid() + "</S:set-prop>\n"); } else { output.Write("<S:set-prop name=\"svn:entry:uuid\">" + sourceControlProvider.GetRepositoryUuid() + "</S:set-prop>\n"); } foreach (KeyValuePair <string, string> property in folder.Properties) { output.Write("<S:set-prop name=\"" + property.Key + "\">" + property.Value + "</S:set-prop>\n"); } } for (int i = 0; i < folder.Items.Count; i++) { ItemMetaData item = folder.Items[i]; if (item.ItemType == ItemType.Folder) { ProcessUpdateReportForDirectory(updateReportRequest, (FolderMetaData)item, output, false, folderWasDeleted); } else { ProcessUpdateReportForFile(updateReportRequest, item, output, folderWasDeleted); } } output.Write("<S:prop></S:prop>\n"); if (rootFolder || existingFolder) { output.Write("</S:open-directory>\n"); } else { output.Write("</S:add-directory>\n"); } } }
public FolderMetaData GetChangedItems(string path, int versionFrom, int versionTo, UpdateReportData reportData) { if (path.StartsWith("/")) { path = path.Substring(1); } var root = (FolderMetaData)QueryItems(path, versionTo, Recursion.Full); if (root != null) { root.Properties.Clear(); } // the item doesn't exist and the request was for a specific target if (root == null && reportData.UpdateTarget != null) { root = new FolderMetaData(); var deletedFile = new DeleteMetaData { ItemRevision = versionTo, Name = reportData.UpdateTarget }; root.Items.Add(deletedFile); return(root); } if (root == null) { throw new FileNotFoundException(path); } /* * var udc = new UpdateDiffCalculator(this); * udc.CalculateDiff(path, versionTo, versionFrom, root, reportData); * if (reportData.UpdateTarget != null) * { * string targetPath = "/" + Helper.CombinePath(path, reportData.UpdateTarget); * foreach (ItemMetaData item in new List<ItemMetaData>(root.Items)) * { * string name = item.Name; * if (name.StartsWith("/") == false) * name = "/" + name; * if (name.Equals(targetPath, StringComparison.InvariantCultureIgnoreCase) == false) * root.Items.Remove(item); * } * }*/ return(root); }
protected override void Handle(IHttpContext context, TFSSourceControlProvider sourceControlProvider) { IHttpRequest request = context.Request; IHttpResponse response = context.Response; string path = GetPath(request); using (XmlReader reader = XmlReader.Create(request.InputStream, Helper.InitializeNewXmlReaderSettings())) { reader.MoveToContent(); object data = null; try { if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "get-locks-report") { SetResponseSettings(response, "text/xml; charset=\"utf-8\"", Encoding.UTF8, 200); response.SendChunked = true; using (var writer = new StreamWriter(response.OutputStream)) { GetLocksReport(writer); } } else if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "update-report") { data = Helper.DeserializeXml <UpdateReportData>(reader); UpdateReportData dt = (UpdateReportData)data; int targetRevision; if (dt != null && dt.TargetRevision != null) { targetRevision = int.Parse(dt.TargetRevision); } else { targetRevision = -1; } /* * const string latestVersion = "Repository.Latest.Version"; * if (RequestCache.Items[latestVersion] == null) * { * RequestCache.Items[latestVersion] = targetRevision = GetSDKObject().GetLastestVersionNum(path); * } * else * { * targetRevision = (int)RequestCache.Items[latestVersion]; * } */ // FolderMetaData update = GetMetadataForUpdate(request, (UpdateReportData)data, sourceControlProvider, out targetRevision); string rep; string str = PathParser.GetLocalPath(request, dt.SrcPath); ItemMetaData up = QueryItems(ParsePath(str, out rep), targetRevision, Recursion.Full); if (up != null) { FolderMetaData update; if (up is FolderMetaData) { update = up as FolderMetaData; } else { update = new FolderMetaData(); update.Items.Add(up); } SetResponseSettings(response, "text/xml; charset=\"utf-8\"", Encoding.UTF8, 200); response.SendChunked = true; using (var output = new StreamWriter(response.OutputStream)) { UpdateReport(sourceControlProvider, (UpdateReportData)data, output, update, targetRevision); } } else { SendTargetDoesNotExistResponse(response); } } else if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "replay-report") { var relayReport = Helper.DeserializeXml <ReplayReportData>(reader); ReplayReport(request, response, sourceControlProvider, relayReport); } else if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "log-report") { data = Helper.DeserializeXml <LogReportData>(reader); SetResponseSettings(response, "text/xml; charset=\"utf-8\"", Encoding.UTF8, 200); response.SendChunked = true; response.BufferOutput = false; using (var output = new StreamWriter(response.OutputStream)) { LogReport(sourceControlProvider, (LogReportData)data, path, output); } } else if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "get-locations") { data = Helper.DeserializeXml <GetLocationsReportData>(reader); SetResponseSettings(response, "text/xml; charset=\"utf-8\"", Encoding.UTF8, 200); response.SendChunked = true; using (var output = new StreamWriter(response.OutputStream)) { GetLocationsReport(sourceControlProvider, (GetLocationsReportData)data, path, output); } } else if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "dated-rev-report") { data = Helper.DeserializeXml <DatedRevReportData>(reader); SetResponseSettings(response, "text/xml; charset=\"utf-8\"", Encoding.UTF8, 200); response.SendChunked = true; using (var output = new StreamWriter(response.OutputStream)) { GetDatedRevReport(sourceControlProvider, (DatedRevReportData)data, output, path); } } else if (reader.NamespaceURI == WebDav.Namespaces.SVN && reader.LocalName == "file-revs-report") { data = Helper.DeserializeXml <FileRevsReportData>(reader); string serverPath = "/"; if (path.IndexOf('/', 9) > -1) { serverPath = path.Substring(path.IndexOf('/', 9)); } SendBlameResponse(request, response, sourceControlProvider, serverPath, (FileRevsReportData)data); return; } else { SendUnknownReportResponse(response); } //if (data != null) //{ // RequestCache.Items["RequestBody"] = data; // DefaultLogger logger = Container.Resolve<DefaultLogger>(); // logger.ErrorFullDetails(new Exception("Logging"), context); //} } catch { RequestCache.Items["RequestBody"] = data; throw; } } }