Exemplo n.º 1
0
        private async Task <ChangesResult> GetChanges(string accessToken, string requestUri, string cursor)
        {
            string rootUri = GetOneDriveRootUri(requestUri);

            requestUri = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", await GetItemUri(accessToken, requestUri, rootUri), "view.changes");

            ChangesResult result = new ChangesResult();

            using (var client = CreateHttpClient(accessToken))
            {
                var next = cursor;
                var ids  = new Dictionary <string, OneDriveModel.ItemInfo>();
                Dictionary <string, object> changes = null;
                var serializer = new JavaScriptSerializer();
                do
                {
                    var uri = requestUri;
                    if (!string.IsNullOrWhiteSpace(next))
                    {
                        uri = string.Format(CultureInfo.InvariantCulture, "{0}?token={1}", requestUri, next);
                    }

                    using (var response = await client.GetAsync(uri))
                    {
                        changes = await ProcessResponse <Dictionary <string, object> >("GetChanges", response);
                    }

                    if (changes.ContainsKey("@changes.resync"))
                    {
                        if (string.IsNullOrEmpty(next))
                        {
                            throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.OneDriveUnableToSync, changes["@changes.resync"]));
                        }

                        // resync
                        next = null;
                        changes["@changes.hasMoreChanges"] = true;
                        result = new ChangesResult();
                        continue;
                    }

                    var items = serializer.ConvertToType <OneDriveModel.OneDriveItemCollection>(changes);

                    // changes
                    if (items != null && items.value != null && items.value.Count > 0)
                    {
                        var subResults = GetChanges(items, ids, rootUri);
                        result.DeletionChanges.AddRange(subResults.DeletionChanges);
                        result.DirectoryChanges.AddRange(subResults.DirectoryChanges);
                        result.FileChanges.AddRange(subResults.FileChanges);
                    }

                    // set next token
                    next = (string)changes["@changes.token"];
                } while ((bool)changes["@changes.hasMoreChanges"]);

                result.Cursor = next;
                return(result);
            }
        }
Exemplo n.º 2
0
        private NextAction Visit <TChange, TChangeContext>(
            IBreakingChangeDefinitions <TChange, TChangeContext> breakingChangeDefinitions,
            TChange typeChange,
            ChangeType changeType,
            TChangeContext typeChangeContext)
        {
            ChangesResult result = EvaluateAndStoreBreakingChanges(breakingChangeDefinitions, typeChange, typeChangeContext);

            if (result == ChangesResult.NoBreakingChanges && changeType == ChangeType.Matched)
            {
                return(NextAction.VisitChildTypes);
            }

            return((StopOnFirstBreakingChange && result == ChangesResult.SomeBreakingChanges)
                                ? NextAction.Stop
                                : NextAction.VisitNextSibling);
        }
Exemplo n.º 3
0
        private static ChangesResult GetChanges(OneDriveModel.OneDriveItemCollection items, Dictionary <string, OneDriveModel.ItemInfo> ids, string rootUri)
        {
            ChangesResult result = new ChangesResult();

            foreach (var item in items.value)
            {
                ids[item.id] = new OneDriveModel.ItemInfo
                {
                    name     = item.name,
                    parentId = item.parentReference.id
                };

                var path = GetPath(ids, item);
                if (item.deleted != null)
                {
                    result.DeletionChanges.Add(new OneDriveModel.OneDriveChange {
                        Path = path, IsDeleted = true
                    });
                }
                else
                {
                    var change = new OneDriveModel.OneDriveChange
                    {
                        ContentUri      = string.Format(CultureInfo.InvariantCulture, "{0}/items/{1}", rootUri, item.id),
                        Path            = path,
                        IsFile          = item.file != null,
                        LastModifiedUtc = item.lastModifiedDateTime.ToUniversalTime()
                    };

                    if (change.IsFile)
                    {
                        result.FileChanges.Add(change);
                    }
                    else
                    {
                        result.DirectoryChanges.Add(change);
                    }
                }
            }

            return(result);
        }
Exemplo n.º 4
0
        internal async Task <ChangeSet> Sync(OneDriveInfo info, IRepository repository, ITracer tracer)
        {
            ChangeSet     changeSet = null;
            string        cursor    = _settings.GetValue(CursorKey);
            ChangesResult changes   = null;

            // use incoming tracer since it is background work
            _tracer = tracer;

            // We truncate cursor value in filename but keep it unharmed in the trace content
            using (_tracer.Step("Getting delta changes with cursor: {0}...", cursor.Truncate(5)))
                using (_tracer.Step("cursor: {0}", cursor))
                {
                    changes = await GetChanges(info.TargetChangeset.Id, info.AccessToken, info.RepositoryUrl, cursor);
                }

            if (changes == null || changes.Count == 0)
            {
                _tracer.Trace("No changes need to be applied.");
                LogMessage(Resources.OneDriveNoChangesFound);
                return(changeSet);
            }

            // for simplicity, use file changes as effective total
            _totals = changes.FileChanges.Count > 0 ? changes.FileChanges.Count : changes.Count;

            string hoststarthtml = Path.Combine(_environment.WebRootPath, Constants.HostingStartHtml);

            FileSystemHelpers.DeleteFileSafe(hoststarthtml);

            using (new Timer(UpdateStatusFile, state: info.TargetChangeset.Id, dueTime: TimeSpan.FromSeconds(5), period: TimeSpan.FromSeconds(5)))
                using (_tracer.Step("Applying {0} changes ...", _totals))
                {
                    LogMessage(Resources.OneDriveApplyingChanges, _totals);

                    // perform action seperately, so that can ensure timestamp on directory
                    // e.g two changes:
                    //  (new) file /a/b/c.txt
                    //  (new) dir  /a/b
                    //  if created dir first then create file. file creation will trigger folder timestamp change.
                    //  which will result in "/a/b" has timestamp from the monent of file creation instead of the timestamp value from server, where value supposed to be set by code specifically.
                    await ApplyChangesParallel(changes.DeletionChanges, info.AccessToken, maxParallelCount : 1, countSuccess : changes.FileChanges.Count == 0);
                    await ApplyChangesParallel(changes.FileChanges, info.AccessToken, maxParallelCount : MaxConcurrentRequests, countSuccess : true);

                    // apply folder changes at last to maintain same timestamp as in OneDrive
                    await ApplyChangesParallel(changes.DirectoryChanges, info.AccessToken, maxParallelCount : 1, countSuccess : changes.FileChanges.Count == 0);

                    _tracer.Trace("{0} succeeded, {1} failed", _successCount, _failedCount);
                    LogMessage(Resources.OneDriveApplyResult, _successCount, _failedCount);

                    string message = _failedCount > 0 ?
                                     string.Format(CultureInfo.CurrentCulture, Resources.OneDrive_SynchronizedWithFailure, _successCount, _totals, _failedCount) :
                                     string.Format(CultureInfo.CurrentCulture, Resources.OneDrive_Synchronized, _totals);

                    // Commit anyway even partial change
                    if (repository.Commit(message, info.AuthorName, info.AuthorEmail))
                    {
                        changeSet = repository.GetChangeSet("HEAD");
                    }

                    if (_failedCount > 0)
                    {
                        // signal deployment failied
                        throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.OneDriveApplyResult, _successCount, _failedCount));
                    }
                }

            // finally keep a copy of the new cursor
            _settings.SetValue(CursorKey, changes.Cursor);

            return(changeSet);
        }