projectkudu/kudu — pull request #227 by HenrikFrystykNielsen (2012-11-21 21:43:40+00:00)
Title: Addition of two new ApiControllers:

Updated with the following changes:

a) Added user messages to resource file
b) Made href URIs in directory browsing absolute
c) Added check against changed files in VfsController so that we don't have a race between getting the file info and opening the file for read or write.
d) Addressed code comments

* * * * *

1) VfsController -- general Kudu file browser.
2) LiveScmVfsController -- git backed file browser

Both controllers provide version protected updating based on etag that avoids lost updates. VfsController is backed by the file system and LiveScmVfsController is backed by a git repository allowing for automatic rebasing and commits.

Both controllers derive from VfsControllerBase but there are differences in how each manages access to the file system as well as handling conflicts. The common functionality is as follows:

a) File and directory browsing: Directories are serialized in a JSON format and files are serialized with the proper content type

b) File etag support: each version of a file has a different etag. The VfsController uses an etag based on the file creation + last modifed type and the LiveScmVfsController uses git commit IDs

c) Range requests: It is possible to request ranges of files using the HTTP/1.1 Range header field in combination with the If-Range header indicating a paticular etag to get the ranges over. Note that this functionality will also be made available as a general Wbe API feature so it is only temporarily placed here.

d) Automatic redirections where URIs pointing to directories but does not have a terminating "/" are automatically redirected to a URI that does. Similarly, URIs pointing to files but do haev a terminating "/" are automatically redirected to a URL that doesn't/

When ScmController updates a resource, the etag included in the If-Match header field is checked that it is present and then the file is updated.

When LiveScmVfsController updates a resource, it first checks out a branch based on the commit ID on which the edit was based (sent in a If-Match header field). It then applies the edits and does a commit and rebase against main. If the rebase succeeds then it sends back a successful response. In case of conflicting updates, it sends back a 409 Conflict response including the conflict as reported by git so that the user can see it. An example of what this looks like is as follows:

HTTP/1.1 409 Conflict
Content-Length: 137
Content-Type: text/plain

<<<<<<< HEAD
abcdef
123456
=======
123456
abcdef
>>>>>>> Committing update from request http://localhost:6478/scmvfs/new/file.txt