Пример #1
0
        /// <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();
                }
            });
        }
Пример #2
0
        /// <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");
                    }
                }
            });
        }
Пример #3
0
        /// <summary>
        /// Push commit to the server.
        /// </summary>
        /// <param name="commit">The commit.</param>
        /// <param name="dataFile">The commit data file.</param>
        /// <param name="onProgress">This is called when there is some progress made.</param>
        public void Push(Commit commit, string dataFile, Action <string> onProgress)
        {
            // construct pull input data
            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 push, 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 push, project is not up-to-date!");
            }

            var clientData = Encoding.UTF8.GetBytes(Authority.ToJson());
            var commitData = Encoding.UTF8.GetBytes(commit.ToJson());

            var filemap = _lastFilemap;

            filemap.AddChanges(RootDir, commit.Files);
            var filemapJson = filemap.ToJson();

            using (var file = new FileStream(dataFile, FileMode.Open))
            {
                var fileNeeded = commit.IsUploadNeeded();
                var datasize   = (fileNeeded ? file.Length : 0) + clientData.Length + commitData.Length + 2 * sizeof(int) + sizeof(bool); // <---

                // begin send
                var stream = Request.BeginSend(ServerAddress + "push", datasize);

                using (var writer = new BinaryWriter(stream))
                {
                    // write client data header
                    writer.Write(clientData.Length);
                    writer.Write(clientData);

                    // write data header
                    writer.Write(commitData.Length);
                    writer.Write(commitData);

                    writer.Write(fileNeeded);

                    if (fileNeeded)
                    {
                        // upload commit data file
                        var readbytes  = 0;
                        var totalbytes = (int)file.Length;
                        int read;
                        var buffer = new byte[64 * 1024];
                        while ((read = file.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            writer.Write(buffer, 0, read);

                            readbytes += read;

                            var prc = (float)readbytes / totalbytes;
                            prc *= 100.0f;
                            onProgress(prc.ToString("f1") + "%");
                        }
                    }

                    Request.EndSend(resp =>
                    {
                        // done!
                        // read response data
                        using (var reader = new BinaryReader(resp))
                        {
                            var message = reader.ReadString();

                            // finalize everything
                            if (message.StartsWith("#RESTORE"))
                            {
                                throw new Exception("Commit failed, error: " + message);
                            }

                            if (message.StartsWith("Failed"))
                            {
                                throw new Exception("Commit failed, error: " + message);
                            }

                            var commitId = reader.ReadInt32();

                            // save commit id
                            File.WriteAllText(commitInfo, commitId.ToString());

                            // save filemap
                            File.WriteAllText(RootDir + ".mysync/last_filemap.json", filemapJson);

                            // refresh
                            Refresh();
                        }
                    });
                }
            }

            // delete data file
            File.Delete(dataFile);

            // ok
        }