예제 #1
0
        public void Sync(DropboxDeployInfo info, string branch)
        {
            if (_settings.GetValue(CursorKey) != info.OldCursor)
            {
                throw new InvalidOperationException(Resources.Error_MismatchDropboxCursor);
            }

            if (!IsEmptyRepo())
            {
                // git checkout --force <branch>
                _repository.Update(branch);
            }

            string prefix = "Partially";
            try
            {
                using (_tracer.Step("Synch with Dropbox"))
                {
                    // Sync dropbox => repository directory
                    ApplyChanges(info);
                }

                prefix = "Successfully";
            }
            finally
            {
                // Commit anyway even partial change
                _repository.Commit(prefix + " sync with dropbox at " + DateTime.UtcNow.ToString("g"), GetAuthor());
            }

            // Save new dropboc cursor
            _tracer.Trace("Update dropbox cursor");
            _settings.SetValue(CursorKey, info.NewCursor);
        }
예제 #2
0
        private void ApplyChanges(DropboxDeployInfo info)
        {
            Semaphore sem = new Semaphore(MaxConcurrentRequests, MaxConcurrentRequests);
            List<Task> tasks = new List<Task>();
            string parent = info.Path.TrimEnd('/') + '/';

            foreach (DropboxDeltaInfo delta in info.Deltas)
            {
                if (!delta.Path.StartsWith(parent, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                var path = delta.Path;
                if (delta.IsDeleted)
                {
                    SafeDelete(parent, path);
                }
                else if (delta.IsDirectory)
                {
                    SafeCreateDir(parent, path);
                }
                else
                {
                    DateTime modified = DateTime.Parse(delta.Modified).ToUniversalTime();
                    if (!IsFileChanged(parent, path, modified))
                    {
                        _tracer.Trace("file unchanged {0}", path);
                        continue;
                    }

                    // throttle concurrent get file dropbox
                    sem.WaitOne();
                    Task task;
                    try
                    {
                        task = GetFileAsync(info, delta).Then(stream =>
                        {
                            using (stream)
                            {
                                SafeWriteFile(parent, path, stream, modified);
                            }
                        }).Catch(catchInfo =>
                        {
                            _tracer.TraceError(catchInfo.Exception);
                            return catchInfo.Throw();
                        })
                        .Finally(() =>
                        {
                            sem.Release();
                        });
                    }
                    catch (Exception ex)
                    {
                        sem.Release();
                        _tracer.TraceError(ex);
                        Task.WaitAll(tasks.ToArray());
                        throw;
                    }

                    tasks.Add(task);
                }
            }

            Task.WaitAll(tasks.ToArray());
        }
예제 #3
0
        private Task<Stream> GetFileAsync(DropboxDeployInfo info, DropboxDeltaInfo delta)
        {
            var parameters = new Dictionary<string, string>
            {
                { "oauth_consumer_key", info.ConsumerKey },
                { "oauth_signature_method", info.SignatureMethod },
                { "oauth_timestamp", info.TimeStamp },
                { "oauth_nonce", delta.Nonce },
                { "oauth_version", info.OAuthVersion },
                { "oauth_token", info.Token },
                { "oauth_signature", delta.Signature }
            };

            var sb = new StringBuilder();
            foreach (var key in parameters.Keys)
            {
                if (sb.Length != 0)
                {
                    sb.Append(',');
                }
                sb.AppendFormat("{0}=\"{1}\"", key, parameters[key]);
            }

            var client = new HttpClient();
            client.BaseAddress = new Uri(DropboxApiContentUri);
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", sb.ToString());
            return client.GetAsync(SandboxFilePath + delta.Path).Then(response =>
            {
                return response.EnsureSuccessStatusCode().Content.ReadAsStreamAsync();
            }).Finally(() => client.Dispose());
        }
예제 #4
0
        public async Task ApplyChangesCoreDeletesFilesForDeltasThatHaveBeenDeleted()
        {
            // Arrange
            var helper = CreateDropboxHelper();
            var fileDeltaInfo = new DropboxDeltaInfo { Path = "foo/bar.txt", IsDeleted = true };
            var dirDeltaInfo = new DropboxDeltaInfo { Path = "foo/baz/", IsDeleted = true, IsDirectory = true };
            var deployInfo = new DropboxDeployInfo { Path = "foo" };
            deployInfo.Deltas = new[] { fileDeltaInfo, dirDeltaInfo };
            string filePath = Path.Combine(helper.Environment.RepositoryPath, "bar.txt"),
                   dirPath = Path.Combine(helper.Environment.RepositoryPath, "baz");

            File.WriteAllBytes(filePath, new byte[0]);
            Directory.CreateDirectory(dirPath);

            // Act
            await helper.ApplyChangesCore(deployInfo);

            // Assert
            Assert.False(File.Exists(filePath));
            Assert.False(Directory.Exists(dirPath));
        }
예제 #5
0
        public async Task ApplyChangesCoreThrowsIfAnyFileTaskFails()
        {
            // Arrange
            var helper = CreateDropboxHelper();
            int processedFiles = 0;
            Mock.Get(helper).Setup(h => h.ProcessFileAsync(It.IsAny<DropboxDeployInfo>(), It.IsAny<DropboxDeltaInfo>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>()))
                            .Callback(() => Interlocked.Increment(ref processedFiles))
                            .Returns(Task.FromResult(0));

            Mock.Get(helper).Setup(h => h.ProcessFileAsync(It.IsAny<DropboxDeployInfo>(), It.IsAny<DropboxDeltaInfo>(), It.IsAny<string>(), "foo/qux.txt", It.IsAny<DateTime>()))
                            .Callback(() => Interlocked.Increment(ref processedFiles))
                            .Returns(GetFailedTask());
            var deployInfo = new DropboxDeployInfo { Path = "foo" };
            deployInfo.Deltas = new[] 
            { 
                new DropboxDeltaInfo { Path = "foo/test.txt" },
                new DropboxDeltaInfo { Path = "foo/bar.txt" },
                new DropboxDeltaInfo { Path = "foo/qux.txt" },
                new DropboxDeltaInfo { Path = "foo/buzz.png" },
                new DropboxDeltaInfo { Path = "foo/baz.php"},
                new DropboxDeltaInfo { Path = "foo/file0.php"},
                new DropboxDeltaInfo { Path = "foo/file1.php"},
                new DropboxDeltaInfo { Path = "foo/file2.php"},
                new DropboxDeltaInfo { Path = "foo/file3.php"},
            };

            // Act
            await ExceptionAssert.ThrowsAsync<HttpRequestException>(async() => await helper.ApplyChangesCore(deployInfo));

            // Assert
            // Ensure we processed other files
            Assert.Equal(deployInfo.Deltas.Count, processedFiles);
        }
예제 #6
0
        public async Task ApplyChangesCoreCreatesDirectoriesForDirectoryDeltas()
        {
            // Arrange
            var helper = CreateDropboxHelper();
            var dirDeltaInfo = new DropboxDeltaInfo { Path = "foo/qux/", IsDirectory = true };
            var deployInfo = new DropboxDeployInfo { Path = "foo" };
            deployInfo.Deltas = new[] { dirDeltaInfo };
            string dirPath = Path.Combine(helper.Environment.RepositoryPath, "qux");

            // Act
            await helper.ApplyChangesCore(deployInfo);

            // Assert
            Assert.True(Directory.Exists(dirPath));
        }