public async Task<ContentChangeSet> CreateFile(string relativePath, ContentItem item)
        {
            var fullPath = GetFullPath(relativePath);

            var response = await
                this._client.Repository.Content.CreateFile(
                    this._ownerName,
                    this._repositoryName,
                    fullPath,
                    new CreateFileRequest(string.Format("Create {0}", relativePath), Encoding.UTF8.GetString(item.ByteContent)));

            var createdItem = response.Content.ToContentItem();
            createdItem.Path = relativePath;

            var changeSet = new ContentChangeSet(response.Commit.Sha, new[] { new ContentItemInfo(createdItem) });
            return changeSet;
        }
        public async Task<ContentChangeSet> UpdateFile(string relativePath, ContentItem item)
        {
            var fullPath = GetFullPath(relativePath);
            var existingItem = await this.GetAllContents(fullPath);
            if (existingItem == null || existingItem.Count == 0)
            {
                throw new FileNotFoundException(string.Format("Can't update \"{0}\", file doesn't exist", relativePath));
            }

            var response = await this._client.Repository.Content.UpdateFile(
                    this._ownerName,
                    this._repositoryName,
                    fullPath,
                    new UpdateFileRequest(string.Format("Update {0}", relativePath), Encoding.UTF8.GetString(item.ByteContent), existingItem[0].Sha));


            var createdItem = response.Content.ToContentItem();
            createdItem.Path = relativePath;

            var changeSet = new ContentChangeSet(response.Commit.Sha, new[] { new ContentItemInfo(createdItem) });
            return changeSet;
        }
        public async Task<ContentChangeSet> GetChangeSet(string relativePath, IContentLoadCriteria criteria)
        {
            // try to get contents of the path first
            var result = await GetAllContents(GetFullPath(relativePath));

            // return nothing if there is not result
            if (result == null || result.Count == 0)
            {
                return null;
            }

            var sha1 = result[0].Sha;

            // get list of all sub trees
            var trees = await this._client.GitDatabase.Tree.GetRecursive(_ownerName, this._repositoryName, sha1);

            // get all blob entries
            var blobs = trees.Tree.Where(x => x.Type == TreeType.Blob);

            // TODO: sha1 here is incorrect, need to get the latest commit sha1 instead
            var items = blobs.Select(blob => blob.ToContentItem()).ToArray();
            var changeSet = new ContentChangeSet(sha1, items.Select(x => new ContentItemInfo(x)).ToArray());

            return changeSet;
        }