Beispiel #1
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");
                    }
                }
            });
        }
Beispiel #2
0
        public static void Discard(string body, HttpListenerResponse response)
        {
            var projectName = "";

            using (var writer = new BinaryWriter(response.OutputStream))
            {
                try
                {
                    var input = DiscardInput.FromJson(body);

                    projectName = input.Authority.ProjectName;
                    if (!Authorization.HasAuthority(input.Authority.AccessToken, projectName))
                    {
                        writer.Write("Failed - project not found!");
                        return;
                    }

                    // request project lock
                    if (ProjectLock.TryLock(projectName, ProjectLock.LockMode.Upload) == ProjectLock.LockMode.Any)
                    {
                        writer.Write("Failed - project is locked!");
                        return;
                    }

                    var projectCollection = ServerCore.Database.GetCollection <CommitModel>(projectName);
                    var commits           = projectCollection.Find(x => x.CommitId >= 0).ToList().OrderBy(x => x.CommitId).ToArray();

                    // select files then pack them
                    // and send to the client
                    var diff = new List <Filemap.FileDiff>();

                    foreach (var file in input.Files)
                    {
                        // select commits which contains this file(which is not removed by the commit) then order by commit and select the first commit.
                        var validCommit = commits.Where(x => x.Files.Any(n => n.Name == file.FileName && n.Operation != 2)).OrderByDescending(x => x.CommitId).FirstOrDefault();

                        if (validCommit != null)
                        {
                            // select the file
                            var validFile = validCommit.Files.First(x => x.Name == file.FileName);

                            diff.Add(new Filemap.FileDiff
                            {
                                FileName = validFile.Name,
                                DiffType = Filemap.FileDiff.Type.Changed,
                                Version  = validFile.Version
                            });
                        }
                        else
                        {
                            Console.WriteLine("Commit not found for file " + file.FileName);
                        }
                    }

                    // create commit
                    var commit = Commit.FromDiff(diff.ToArray());

                    // write commit in json format
                    var commitJson = commit.ToJson();
                    writer.Write(commitJson);

                    // build commit diff data file
                    var dir          = "data/" + projectName + "/";
                    var tempDataFile = "temp_send_" + input.Authority.Username + ".zip";
                    commit.Build(dir, tempDataFile, delegate(int progress)
                    {
                        var lastSend = DateTime.Now;
                        if ((DateTime.Now - lastSend).TotalSeconds >= 1.0f)
                        {
                            writer.Write(false);
                            writer.Write(progress);
                        }
                    });

                    writer.Write(true);

                    // send commit diff data file
                    using (var nfs = new NetFileStream(tempDataFile, onError: delegate
                    {
                        // user lost connection or closed the client
                        // before the whole data file is sent
                        Console.WriteLine("User '" + input.Authority.Username + "' canceled commit download.");
                        ProjectLock.Unlock(projectName);
                    }))
                    {
                        nfs.Upload(response.OutputStream);
                    }

                    File.Delete(tempDataFile);
                }
                catch (Exception ex)
                {
                    writer.Write("Failed - invalid protocol/connection error! Error: " + ex);
                    Console.WriteLine(ex);
                    ProjectLock.Unlock(projectName);
                }
            }
            ProjectLock.Unlock(projectName);
        }