public IList <Commit> ProcessCommits(string urlString) { IList <Commit> commits = new List <Commit>(); try { if (!string.IsNullOrEmpty(urlString)) { var stringTask = client.GetStringAsync(urlString).Result; commits = Commit.FromJson(stringTask); } return(commits); } catch (Exception ex) { throw ex; } }
/// <summary> /// Discard selected files. /// </summary> /// <param name="files">Files selected for discard.</param> /// <param name="onProgress">This is called when there is some progress made.</param> public void Discard(Filemap.FileDiff[] files, Action <string> onProgress) { var dataJson = new PullInput { Authority = Authority }; var lastCommitId = -1; Request.Send(ServerAddress + "getcommit", dataJson.ToJson(), stream => { using (var reader = new BinaryReader(stream)) { var message = reader.ReadString(); if (message == "Done") { lastCommitId = reader.ReadInt32(); } else { throw new Exception("Cannot discard, Error: <br>" + message); } } }); // select current commit id var commitInfo = RootDir + ".mysync/commit_info.txt"; var currentCommitId = File.Exists(commitInfo) ? int.Parse(File.ReadAllText(commitInfo)) : -1; if (lastCommitId > currentCommitId) { throw new Exception("Cannot discard, project is not up-to-date!"); } // select all files that are not 'created' var filesToDownload = new List <Filemap.File>(); foreach (var file in files) { if (file.DiffType != Filemap.FileDiff.Type.Created) { filesToDownload.Add(new Filemap.File { FileName = file.FileName }); } } var input = new DiscardInput { Authority = Authority, Files = filesToDownload.ToArray() }; // remove new files var toDelete = 0; foreach (var file in files) { if (file.DiffType == Filemap.FileDiff.Type.Created) // delete all 'created' files { var fileName = RootDir + file.FileName; // delete file File.Delete(fileName); DirectoryHelper.DeleteIfEmpty(fileName); toDelete++; } } // check if there are files only for delete if (toDelete == files.Length) { return; } // download original files from server Request.Send(ServerAddress + "discard", input.ToJson(), stream => { using (var reader = new BinaryReader(stream)) { var commitJson = reader.ReadString(); while (true) { var state = reader.ReadBoolean(); if (state) { break; } var progress = reader.ReadInt32(); if (progress >= 0) { onProgress("Building commit..."); } } // download var dataFile = RootDir + ".mysync/commit_recv.zip"; // send commit diff data file using (var nfs = new NetFileStream(dataFile, onError: delegate { // throw error throw new Exception("Error when downloading commit data file"); })) { nfs.Download(stream, delegate(long bytes, long sentBytes) { // show progress var prc = (sentBytes / (float)bytes) * 100; onProgress?.Invoke(prc.ToString("f1") + "%"); }); } var commit = Commit.FromJson(commitJson); try { // downloaded // now apply changes commit.Apply(RootDir, dataFile, true); } catch (Exception ex) { throw new Exception("Error when applying commit data file"); } } }); }
/// <summary> /// Pull commits from server and apply. /// </summary> /// <param name="onProgress">This is called when there is some progress made.</param> public void Pull(Action <string> onProgress) { var commitInfo = RootDir + ".mysync/commit_info.txt"; // select current commit id var currentCommitId = File.Exists(commitInfo) ? int.Parse(File.ReadAllText(commitInfo)) : -1; // construct pull input data var dataJson = new PullInput { Authority = Authority, CommitId = currentCommitId }; // send pull request Request.Send(ServerAddress + "pull", dataJson.ToJson(), stream => { using (var reader = new BinaryReader(stream)) { if (!reader.ReadBoolean()) { // error! throw new WarningException(reader.ReadString()); } while (!reader.ReadBoolean()) { var progress = reader.ReadInt32(); if (progress >= 0) { onProgress(progress + "%"); } } var body = reader.ReadString(); Console.WriteLine(body); Commit commit; // try convert commit data try { commit = Commit.FromJson(body); } catch { throw new WarningException("There is no any changes to download."); } var commitId = reader.ReadInt32(); Console.WriteLine(@"commit id: " + commitId); var hasFile = reader.ReadBoolean(); var dataFile = RootDir + ".mysync/commit_recv.zip"; if (hasFile) { using (var fs = File.Create(dataFile)) { var totalbytes = reader.ReadInt64(); var readbytes = 0; int read; var buffer = new byte[64 * 1024]; while ((read = reader.Read(buffer, 0, buffer.Length)) > 0) { fs.Write(buffer, 0, read); readbytes += read; var prc = (float)readbytes / totalbytes; prc *= 100.0f; if (prc >= 0) { onProgress(prc.ToString("f1") + "%"); } } } } // apply the commit commit.Apply(RootDir, dataFile, hasFile); // remove data file if (hasFile) { File.Delete(dataFile); } // update filemap _lastFilemap.AddChanges(RootDir, commit.Files); File.WriteAllText(RootDir + ".mysync/last_filemap.json", _lastFilemap.ToJson()); // save commit id File.WriteAllText(commitInfo, commitId.ToString()); // refresh Refresh(); } }); }
public static void Push(HttpListenerRequest request, HttpListenerResponse response) { var projectName = ""; try { using (var reader = new BinaryReader(request.InputStream)) { using (var writer = new BinaryWriter(response.OutputStream)) { try { var authority = ProjectAuthority.FromJson(Encoding.UTF8.GetString( reader.ReadBytes(reader.ReadInt32()) )); projectName = authority.ProjectName; // validate project name, password and check permisions from clientData if (!Authorization.HasAuthority(authority.AccessToken, projectName)) { writer.Write("Failed - project not found!"); return; } // request project lock if (ProjectLock.TryLock(projectName, ProjectLock.LockMode.Upload) != ProjectLock.LockMode.None) { writer.Write("Failed - project is locked!"); return; } // read commit var commitData = reader.ReadBytes(reader.ReadInt32()); var commit = Commit.FromJson(Encoding.UTF8.GetString(commitData)); var hasFile = reader.ReadBoolean(); if (hasFile) { Console.WriteLine("Receiving file..."); try { // read data file using (var fs = File.Create("temp_recv.zip")) { try { int read; var buffer = new byte[64 * 1024]; while ((read = reader.Read(buffer, 0, buffer.Length)) > 0) { fs.Write(buffer, 0, read); } } catch { // user lost connection or closed the client // before the whole data file arrived Console.WriteLine("User '" + authority.Username + "' canceled commit upload."); ProjectLock.Unlock(projectName); return; } } } catch { // user lost connection or closed the client // before the whole data file arrived Console.WriteLine("User '" + authority.Username + "' commit upload failed."); ProjectLock.Unlock(projectName); return; } } // --- from now - this part CAN'T fail, if so, the whole project may be incorrect after this! var projectDir = "data/" + projectName; // make commited files backup commit.Backup(projectDir); int commitId; try { // downloaded // now apply changes commit.Apply(projectDir, "temp_recv.zip", hasFile); // add commit to projects database var projectCollection = ServerCore.Database.GetCollection <CommitModel>(projectName); commitId = (int)projectCollection.Count(FilterDefinition <CommitModel> .Empty) + 1; // build commit var commitModel = new CommitModel { CommitId = commitId, CommitDescription = commit.Description, Files = new CommitModel.FileDiff[commit.Files.Length] }; for (var i = 0; i < commit.Files.Length; i++) { var file = commit.Files[i]; commitModel.Files[i] = new CommitModel.FileDiff { Name = file.FileName, Version = file.Version, Operation = (int)file.DiffType }; } // insert projectCollection.InsertOne(commitModel); // delete zip file if exists if (hasFile) { File.Delete("temp_recv.zip"); } } catch (Exception ex) { Console.WriteLine("Failed to apply commit from user '" + authority.Username + "'"); writer.Write("#RESTORE Failed - error when updating project! Error: " + ex); // restore backup commit.RestoreBackup(projectDir); // UNLOCK ProjectLock.Unlock(projectName); return; } // ok, we are out of the danger zone. // return message writer.Write("Done!"); writer.Write(commitId); // clean backups commit.CleanBackups(projectDir); Console.WriteLine("User '" + authority.Username + "' pushed changes!"); } catch (Exception ex) { writer.Write("Failed - invalid protocol/connection error! Error: " + ex); Console.WriteLine("PUSH failed"); ProjectLock.Unlock(projectName); } } } } catch { // this shouldn't be possible, // but anyway handle exceptions here Console.WriteLine("PUSH failed"); ProjectLock.Unlock(projectName); } Console.WriteLine("Push done"); ProjectLock.Unlock(projectName); }