|Revision 143, 6.4 KB checked in by lele@…, 4 years ago (diff)|
Darcs backend for Trac
It should work well enough also with current (at the time of writing) 0.11 and even with 0.10. No guarantee!
To use the module you can either install it or make an egg and copy it in the right place.
You can install the module the usual way:
$ python setup.py install [--prefix /usr/local]
Otherwise you can make an egg:
$ python setup.py bdist_egg
and either install it globally with:
$ easy_install dist/TracDarcs-someversion.egg
or manually copy the egg from the "dist" subdir into the environment's "plugins" subdirectory
In general, follow the directions in TracPlugins.
The entire darcs change history is imported into the database, using the output of darcs changes --xml-output --summary --reverse.
A check for newer patches is performed everytime the DarcsRepository object is created, and any new patches are immediately imported into the database.
After that the darcs repository is used only for fetching the contents of a file: with darcs 2.x we use darcs query contents, while with darcs 1.x we have to do ugly tricks; at the extreme, darcs annotate output is massaged by ann2ascii.py to fetch the contents of a file at any given point in time.
Each changeset is assigned a revision number according to their order in the output of darcs changes --xml-output --summary --reverse. The first patch gets a revision number of 1, and second revision number 2 etc...
This assumes that the patches in a darcs repository NEVER get reordered or deleted. This condition is satisfied as long as commands such as darcs unpull or darcs optimize are not performed.
For performance reasons, the backend creates and maintains a few other tables, where it keeps darcs specific information. The following tables are automatically created at upgrade time and populated by sync (see components.py).
Each row represents a darcs changeset:
create table darcs_changesets ( repo_id text, rev integer, hash text, name text, primary key (repo_id, rev));
- repository containing this changeset
- the revision number assigned
- the unique patch identifier assigned by darcs
- the name of the darcs patch
Each row represents a single node: a node is either a file or a directory which has its history stored in the repository.
a node doesn't have a particular name or content but, for a given revision, its name and content will be well defined.
create table darcs_nodes ( repo_id text, node_id integer, node_type text, add_rev integer, remove_rev integer, primary key (repo_id, node_id) );
- is one of (dbutil.NODE_FILE_TYPE, dbutil.NODE_DIR_TYPE)
- is the revision that added this node
- is the revision that removed this node (possibly NULL)
Each row represents a node change for a particular revision. Only one entry can exist for a node in each revision. Of course, if there are no changes to the node then no entries will be present! :)
create table darcs_node_changes ( repo_id text, node_id integer, rev integer, path text, parent_id integer, the_change text, primary key (repo_id, node_id,rev) );
- one of following (defined in dbutil.py): CHANGE_ADDED, CHANGE_REMOVED, CHANGE_MOVED, CHANGE_EDITED, CHANGE_MOVED_EDITED
- the node id for the node's parent directory
- the path of the node at the end of revision 'rev': when change is CHANGE_REMOVED then 'path' is the previous path.
A cache of file contents: as soon as the content of any file at any particular revision is requested for the first time, it's computed and stored here, so succeeding requests won't require executing darcs at all.
this may quickly grow in size! OTOH, you can just delete all the rows at any time, the content will be recomputed when reasked.
create table darcs_cache ( repo_id text, node_id integer, rev integer, content blob, size integer, primary key (repo_id, node_id,rev) );
Some sample queries
Get all existing nodes as of revision r
select dnc.node_id as node_id, max(dnc.rev) as rev from darcs_node_changes as dnc, darcs_nodes as dn where dnc.node_id = dn.node_id and dnc.rev <= r and dnc.repo_id = dn.repo_id and dnc.repo_id = 'somerepo' and (dn.remove_rev is null or dn.remove_rev > r) group by dnc.node_id
Get all latest nodes
select dnc.node_id as node_id, max(dnc.rev) as rev from darcs_node_changes as dnc, darcs_nodes as dn where dnc.node_id = dn.node_id and dn.remove_rev is null and dnc.repo_id = dn.repo_id and dnc.repo_id = 'somerepo' group by dnc.node_id
Get node_id of /some/path p, as of revision r
select dnc.node_id as node_id from darcs_node_changes as dnc, (node_rev(r)) as nr where dnc.node_id = nr.node_id and dnc.rev = nr.rev and dnc.repo_id = nr.repo_id and dnc.repo_id = 'somerepo' and dnc.path = p
Get history of node_id nid, till revision r
select * from darcs_node_changes as dnc where dnc.node_id = nid and dnc.rev <= r and dnc.repo_id = 'somerepo'
Get children of node_id nid, as of revision r
select dnc.node_id as node_id from darcs_node_changes as dnc, (node_rev(r)) as nr where dnc.node_id = nr.node_id and dnc.rev = nr.rev and dnc.parent_id = nid and dnc.repo_id = nr.repo_id and dnc.repo_id = 'somerepo'