1 A few bits about the RCS backends
7 ``web-edit'' means that a page is edited by using the web (CGI) interface
8 as opposed to using a editor and the RCS interface.
13 Subversion was the first RCS to be supported by ikiwiki.
15 ### How does it work internally?
19 RCS commits from the outside are installed into M.
21 There is a working copy of M (a checkout of M): W.
23 HTML is generated from W. rcs_update() will update from M to W.
25 CGI operates on W. rcs_commit() will commit from W to M.
27 For all the gory details of how ikiwiki handles this behind the scenes,
28 see [[commit-internals]].
30 You browse and web-edit the wiki on W.
32 W "belongs" to ikiwiki and should not be edited directly.
37 Regarding the repository layout: There are two darcs repositories. One is the `srcdir`, the other we'll call `master`.
39 * HTML is generated from `srcdir`.
40 * CGI edits happen in `srcdir`.
41 * The backend pulls updates from `master` into `srcdir`, i.e. darcs commits should happen to `master`.
42 * `master` calls ikiwiki (through a wrapper) in its apply posthook, i.e. `master/_darcs/prefs/defaults` should look like this:
44 apply posthook ikiwrap
47 * The backend pushes CGI edits from `srcdir` back into `master` (triggering the apply hook).
48 * The working copies in `srcdir` and `master` should *not* be touched by the user, only by the CGI or darcs, respectively.
52 Regarding the Git support, Recai says:
54 I have been testing it for the past few days and it seems satisfactory. I
55 haven't observed any race condition regarding the concurrent blog commits
56 and it handles merge conflicts gracefully as far as I can see.
58 (After about a year, git support is nearly as solid as subversion support --[[Joey]])
60 As you may notice from the patch size, GIT support is not so trivial to
61 implement (for me, at least). It has some drawbacks (especially wrt merge
62 which was the hard part). GIT doesn't have a similar functionality like
63 'svn merge -rOLD:NEW FILE' (please see the relevant comment in `_merge_past`
64 for more details), so I had to invent an ugly hack just for the purpose.
66 > I was looking at this, and WRT the problem of uncommitted local changes,
67 > it seems to me you could just git-stash them now that git-stash exists.
68 > I think it didn't when you first added the git support.. --[[Joey]]
71 >> Yes, git-stash had not existed before. What about sth like below? It
72 >> seems to work (I haven't given much thought on the specific implementation
73 details). --[[roktas]]
75 >> # create test files
85 >> sed -e 's/2/2ME/' page >page.me # my changes
93 >> sed -e 's/5/5SOMEONE/' page >page.someone # someone's changes
102 >> # create a test repository
108 >> git commit -m init
110 >> # save the current HEAD
111 >> ME=$(git rev-list HEAD -- page)
112 >> $EDITOR page # assume that I'm starting to edit page via web
114 >> # simulates someone's concurrent commit
115 >> cp ../page.someone page
116 >> git commit -m someone -- page
118 >> # My editing session ended, the resulting content is in page.me
119 >> cp ../page.me page
128 >> # let's start to save my uncommitted changes
130 >> git stash save "changes by me"
131 >> # we've reached a clean state
140 >> # roll-back to the $ME state
141 >> git reset --soft $ME
142 >> # now, the file is marked as modified
143 >> git stash save "changes by someone"
145 >> # now, we're at the $ME state
154 >> stash@{0}: On master: changes by someone
155 >> stash@{1}: On master: changes by me
157 >> # first apply my changes
158 >> git stash apply stash@{1}
167 >> git commit -m me -- page
169 >> # apply someone's changes
170 >> git stash apply stash@{0}
179 >> git commit -m me+someone -- page
181 By design, Git backend uses a "master-clone" repository pair approach in contrast
182 to the single repository approach (here, _clone_ may be considered as the working
183 copy of a fictious web user). Even though a single repository implementation is
184 possible, it somewhat increases the code complexity of backend (I couldn't figure
185 out a uniform method which doesn't depend on the prefered repository model, yet).
186 By exploiting the fact that the master repo and _web user_'s repo (`srcdir`) are all
187 on the same local machine, I suggest to create the latter with the "`git clone -l -s`"
188 command to save disk space.
190 Note that, as a rule of thumb, you should always put the rcs wrapper (`post-update`)
191 into the master repository (`.git/hooks/`).
193 Here is how a web edit works with ikiwiki and git:
195 * ikiwiki cgi modifies the page source in the clone
196 * git-commit in the clone
197 * git push origin master, pushes the commit from the clone to the master repo
198 * the master repo's post-update hook notices this update, and runs ikiwiki
199 * ikiwiki notices the modifies page source, and compiles it
201 Here is a how a commit from a remote repository works:
203 * git-commit in the remote repository
204 * git-push, pushes the commit to the master repo on the server
205 * (Optionally, the master repo's pre-receive hook runs, and checks that the
206 update only modifies files that the pushing user is allowed to update.
207 If not, it aborts the receive.)
208 * the master repo's post-update hook notices this update, and runs ikiwiki
209 * ikiwiki notices the modifies page source, and compiles it
213 The Mercurial backend is still in a early phase, so it may not be mature
214 enough, but it should be simple to understand and use.
216 As Mercurial is a distributed RCS, it lacks the distinction between
217 repository and working copy (every wc is a repo).
219 This means that the Mercurial backend uses directly the repository as
220 working copy (the master M and the working copy W described in the svn
221 example are the same thing).
223 You only need to specify 'srcdir' (the repository M) and 'destdir' (where
224 the HTML will be generated).
228 RCS commit from the outside are installed into M.
230 M is directly used as working copy (M is also W).
232 HTML is generated from the working copy in M. rcs_update() will update
233 to the last committed revision in M (the same as 'hg update').
234 If you use an 'update' hook you can generate automatically the HTML
235 in the destination directory each time 'hg update' is called.
237 CGI operates on M. rcs_commit() will commit directly in M.
239 If you have any question or suggestion about the Mercurial backend
240 please refer to [Emanuele](http://nerd.ocracy.org/em/)
246 There is a patch that needs a bit of work linked to from [[todo/rcs]].
250 In normal use, monotone has a local database as well as a workspace/working copy.
251 In ikiwiki terms, the local database takes the role of the master repository, and
252 the srcdir is the workspace. As all monotone workspaces point to a default
253 database, there is no need to tell ikiwiki explicitly about the "master" database. It
256 The backend currently supports normal committing and getting the history of the page.
257 To understand the parallel commit approach, you need to understand monotone's
258 approach to conflicts:
260 Monotone allows multiple micro-branches in the database. There is a command,
261 `mtn merge`, that takes the heads of all these branches and merges them back together
262 (turning the tree of branches into a dag). Conflicts in monotone (at time of writing)
263 need to be resolved interactively during this merge process.
264 It is important to note that having multiple heads is not an error condition in a
265 monotone database. This condition will occur in normal use. In this case
266 'update' will choose a head if it can, or complain and tell the user to merge.
268 For the ikiwiki plugin, the monotone ikiwiki plugin borrows some ideas from the svn ikiwiki plugin.
269 On prepedit() we record the revision that this change is based on (I'll refer to this as the prepedit revision). When the web user
270 saves the page, we check if that is still the current revision. If it is, then we commit.
271 If it isn't then we check to see if there were any changes by anyone else to the file
272 we're editing while we've been editing (a diff bewteen the prepedit revision and the current rev).
273 If there were no changes to the file we're editing then we commit as normal.
275 It is only if there have been parallel changes to the file we're trying to commit that
276 things get hairy. In this case the current approach is to
277 commit the web changes as a branch from the prepedit revision. This
278 will leave the repository with multiple heads. At this point, all data is saved.
279 The system then tries to merge the heads with a merger that will fail if it cannot
280 resolve the conflict. If the merge succeeds then everything is ok.
282 If that merge failed then there are conflicts. In this case, the current code calls
283 merge again with a merger that inserts conflict markers. It commits this new
284 revision with conflict markers to the repository. It then returns the text to the
285 user for cleanup. This is less neat than it could be, in that a conflict marked
286 revision gets committed to the repository.