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); }
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()); }
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()); }
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)); }
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); }
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)); }