Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add the ability to create a child-project repository that can pull from its parent repository but never push back. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
dddc58da657a1a7cf09e271fe3fc0c21 |
| User & Date: | drh 2016-08-16 16:17:05.685 |
Context
|
2016-08-16
| ||
| 17:25 | Add the /setup_ucap_list built-in documentation page. Improvements to the /setup_ulist_notes built-in documentation page. ... (check-in: 70d898fe3c user: drh tags: trunk) | |
| 16:25 | Merge recent trunk enhancements. ... (check-in: f6d4a2bfe3 user: drh tags: unversioned-files) | |
| 16:17 | Add the ability to create a child-project repository that can pull from its parent repository but never push back. ... (check-in: dddc58da65 user: drh tags: trunk) | |
| 15:32 | Add the ability to create a child-project repository that can pull from its parent repository but never push back. ... (Closed-Leaf check-in: 0ab5ad5f36 user: drh tags: child-projects) | |
|
2016-08-15
| ||
| 15:18 | update change-log ... (check-in: 4f3054bcb3 user: jan.nijtmans tags: trunk) | |
Changes
Changes to src/bundle.c.
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
db_multi_exec(
"INSERT INTO bconfig(bcname,bcvalue)"
" VALUES('mtime',datetime('now'));"
);
db_multi_exec(
"INSERT INTO bconfig(bcname,bcvalue)"
" SELECT name, value FROM config"
| | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
db_multi_exec(
"INSERT INTO bconfig(bcname,bcvalue)"
" VALUES('mtime',datetime('now'));"
);
db_multi_exec(
"INSERT INTO bconfig(bcname,bcvalue)"
" SELECT name, value FROM config"
" WHERE name IN ('project-code','parent-project-code');"
);
/* Directly copy content from the repository into the bundle as long
** as the repository content is a delta from some other artifact that
** is also in the bundle.
*/
db_multi_exec(
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
while( db_step(&s)==SQLITE_ROW ){
fossil_print("access-url: %-54s %s\n", db_column_text(&s, 0),
db_column_text(&s, 1));
}
db_finalize(&s);
}
/*
** COMMAND: info
**
** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME? ?OPTIONS?
**
** With no arguments, provide information about the current tree.
| > > > > > > > > > > > | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
while( db_step(&s)==SQLITE_ROW ){
fossil_print("access-url: %-54s %s\n", db_column_text(&s, 0),
db_column_text(&s, 1));
}
db_finalize(&s);
}
/*
** Show the parent project, if any
*/
static void showParentProject(void){
const char *zParentCode;
zParentCode = db_get("parent-project-code",0);
if( zParentCode ){
fossil_print("derived-from: %s %s\n", zParentCode, db_get("parent-project-name",""));
}
}
/*
** COMMAND: info
**
** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME? ?OPTIONS?
**
** With no arguments, provide information about the current tree.
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
db_open_config(0, 0);
db_open_repository(g.argv[2]);
db_record_repository_filename(g.argv[2]);
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
extraRepoInfo();
return;
}
db_find_and_open_repository(0,0);
verify_all_options();
if( g.argc==2 ){
int vid;
/* 012345678901234 */
db_record_repository_filename(0);
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
if( g.localOpen ){
fossil_print("repository: %s\n", db_repository_filename());
fossil_print("local-root: %s\n", g.zLocalRoot);
}
if( verboseFlag ) extraRepoInfo();
if( g.zConfigDbName ){
fossil_print("config-db: %s\n", g.zConfigDbName);
}
fossil_print("project-code: %s\n", db_get("project-code", ""));
vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
if( vid ){
show_common_info(vid, "checkout:", 1, 1);
}
fossil_print("check-ins: %d\n",
db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
}else{
| > > | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
db_open_config(0, 0);
db_open_repository(g.argv[2]);
db_record_repository_filename(g.argv[2]);
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
showParentProject();
extraRepoInfo();
return;
}
db_find_and_open_repository(0,0);
verify_all_options();
if( g.argc==2 ){
int vid;
/* 012345678901234 */
db_record_repository_filename(0);
fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
if( g.localOpen ){
fossil_print("repository: %s\n", db_repository_filename());
fossil_print("local-root: %s\n", g.zLocalRoot);
}
if( verboseFlag ) extraRepoInfo();
if( g.zConfigDbName ){
fossil_print("config-db: %s\n", g.zConfigDbName);
}
fossil_print("project-code: %s\n", db_get("project-code", ""));
showParentProject();
vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
if( vid ){
show_common_info(vid, "checkout:", 1, 1);
}
fossil_print("check-ins: %d\n",
db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
}else{
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
145 146 147 148 149 150 151 |
@ <tr><th>Duration Of Project:</th><td>
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
" + 0.99");
@ %d(n) days or approximately %.2f(n/365.2425) years.
@ </td></tr>
p = db_get("project-code", 0);
if( p ){
| | > > > > > > | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
@ <tr><th>Duration Of Project:</th><td>
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
" + 0.99");
@ %d(n) days or approximately %.2f(n/365.2425) years.
@ </td></tr>
p = db_get("project-code", 0);
if( p ){
@ <tr><th>Project ID:</th>
@ <td>%h(p) %h(db_get("project-name",""))</td></tr>
}
p = db_get("parent-project-code", 0);
if( p ){
@ <tr><th>Parent Project ID:</th>
@ <td>%h(p) %h(db_get("parent-project-name",""))</td></tr>
}
/* @ <tr><th>Server ID:</th><td>%h(db_get("server-code",""))</td></tr> */
@ <tr><th>Fossil Version:</th><td>
@ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
@ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
@ </td></tr>
@ <tr><th>SQLite Version:</th><td>%.19s(sqlite3_sourceid())
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
@ <tr><th>Schema Version:</th><td>%h(g.zAuxSchema)</td></tr>
|
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
int urlOptional = 0;
if( find_option("autourl",0,0)!=0 ){
urlOptional = 1;
urlFlags = 0;
}
zHttpAuth = find_option("httpauth","B",1);
if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
if( find_option("private",0,0)!=0 ){
*pSyncFlags |= SYNC_PRIVATE;
}
if( find_option("verbose","v",0)!=0 ){
*pSyncFlags |= SYNC_VERBOSE;
}
/* The --verily option to sync, push, and pull forces extra igot cards
| > | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
int urlOptional = 0;
if( find_option("autourl",0,0)!=0 ){
urlOptional = 1;
urlFlags = 0;
}
zHttpAuth = find_option("httpauth","B",1);
if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
if( (*pSyncFlags) & SYNC_FROMPARENT ) urlFlags &= ~URL_REMEMBER;
if( find_option("private",0,0)!=0 ){
*pSyncFlags |= SYNC_PRIVATE;
}
if( find_option("verbose","v",0)!=0 ){
*pSyncFlags |= SYNC_VERBOSE;
}
/* The --verily option to sync, push, and pull forces extra igot cards
|
| ︙ | ︙ | |||
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
** pull, remote-url, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --ipv4 Use only IPv4, not IPv6
** --once Do not remember URL for subsequent syncs
** --proxy PROXY Use the specified HTTP proxy
** --private Pull private branches too
** -R|--repository REPO Repository to pull into
** --ssl-identity FILE Local SSL credentials, if requested by remote
** --ssh-command SSH Use SSH as the "ssh" command
** -v|--verbose Additional (debugging) output
** --verily Exchange extra information with the remote
** to ensure no content is overlooked
**
** See also: clone, config pull, push, remote-url, sync
*/
void pull_cmd(void){
unsigned configFlags = 0;
unsigned syncFlags = SYNC_PULL;
process_sync_args(&configFlags, &syncFlags);
/* We should be done with options.. */
verify_all_options();
client_sync(syncFlags, configFlags, 0);
}
| > > > > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
** pull, remote-url, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --from-parent-project Pull content from the parent project
** --ipv4 Use only IPv4, not IPv6
** --once Do not remember URL for subsequent syncs
** --proxy PROXY Use the specified HTTP proxy
** --private Pull private branches too
** -R|--repository REPO Repository to pull into
** --ssl-identity FILE Local SSL credentials, if requested by remote
** --ssh-command SSH Use SSH as the "ssh" command
** -v|--verbose Additional (debugging) output
** --verily Exchange extra information with the remote
** to ensure no content is overlooked
**
** See also: clone, config pull, push, remote-url, sync
*/
void pull_cmd(void){
unsigned configFlags = 0;
unsigned syncFlags = SYNC_PULL;
if( find_option("from-parent-project",0,0)!=0 ){
syncFlags |= SYNC_FROMPARENT;
}
process_sync_args(&configFlags, &syncFlags);
/* We should be done with options.. */
verify_all_options();
client_sync(syncFlags, configFlags, 0);
}
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
1389 1390 1391 1392 1393 1394 1395 | static const char zBriefFormat[] = "Round-trips: %d Artifacts sent: %d received: %d\r"; #if INTERFACE /* ** Flag options for controlling client_sync() */ | | | | | | | > | 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 |
static const char zBriefFormat[] =
"Round-trips: %d Artifacts sent: %d received: %d\r";
#if INTERFACE
/*
** Flag options for controlling client_sync()
*/
#define SYNC_PUSH 0x0001
#define SYNC_PULL 0x0002
#define SYNC_CLONE 0x0004
#define SYNC_PRIVATE 0x0008
#define SYNC_VERBOSE 0x0010
#define SYNC_RESYNC 0x0020
#define SYNC_FROMPARENT 0x0080
#endif
/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
return x>0.0 ? x : -x;
|
| ︙ | ︙ | |||
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 |
int nArtifactRcvd = 0; /* Total artifacts received */
const char *zOpType = 0;/* Push, Pull, Sync, Clone */
double rSkew = 0.0; /* Maximum time skew */
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
&& configRcvMask==0 && configSendMask==0 ) return 0;
transport_stats(0, 0, 1);
socket_global_init();
memset(&xfer, 0, sizeof(xfer));
xfer.pIn = &recv;
xfer.pOut = &send;
xfer.mxSend = db_get_int("max-upload", 250000);
| > > > > > > > > > > > | 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 |
int nArtifactRcvd = 0; /* Total artifacts received */
const char *zOpType = 0;/* Push, Pull, Sync, Clone */
double rSkew = 0.0; /* Maximum time skew */
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
&& configRcvMask==0 && configSendMask==0 ) return 0;
if( syncFlags & SYNC_FROMPARENT ){
configRcvMask = 0;
configSendMask = 0;
syncFlags &= ~(SYNC_PUSH);
zPCode = db_get("parent-project-code", 0);
if( zPCode==0 || db_get("parent-project-name",0)==0 ){
fossil_fatal("there is no parent project: set the 'parent-project-code'"
" and 'parent-project-name' config parameters set in order"
" to pull from a parent project");
}
}
transport_stats(0, 0, 1);
socket_global_init();
memset(&xfer, 0, sizeof(xfer));
xfer.pIn = &recv;
xfer.pOut = &send;
xfer.mxSend = db_get_int("max-upload", 250000);
|
| ︙ | ︙ |
Added www/childprojects.wiki.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<title>Child Projects</title>
<h2>Background</h2>
The default behavior of Fossil is to share everything (all check-ins,
tickets, wiki, etc) between all clients and all servers. Such a policy
helps to promote a cohesive design for a cathedrial-style project run
by a small cliche of developers - the sort of project for which Fossil
was designed.
But sometimes it is desirable to branch off a side project that does not
sync back to the master but does continue to track changes in the master.
For example, the master project might be an open-source project like
[https://www.sqlite.org/|SQLite] and a team might want to do a proprietary
closed-source enhancement to that master project in a separate repository.
All changes in the master project should flow forward into the derived
project, but care must be taken to prevent proprietary content from the
derived project from leaking back into the master.
<h2>Child Projects</h2>
A scenario such as the above can be accomplished in Fossil by creating
a child project. The child project is able to freely pull from the parent,
but the parent cannot push or pull from the child nor is the child able to
push to the parent. Content flows from parent to child only, and then only
at the request of the child.
<h2>Creating a Child Project</h2>
To create a new child project, first clone the parent. Then make manual
SQL changes to the child repository as follows:
<blockquote><verbatim>
UPDATE config SET name='parent-project-code' WHERE name='project-code';
UPDATE config SET name='parent-project-name' WHERE name='project-name';
INSERT INTO config(name,value)
VALUES('project-code',lower(hex(randomblob(20))));
INSERT INTO config(name,value)
VALUES('project-name','CHILD-PROJECT-NAME');
</verbatim></blockquote>
Modify the CHILD-PROJECT-NAME in the last statement to be the name of
the child project, of course.
The repository is now a separate project, independent from its parent.
Clone the new project to the developers as needed.
The child project and the parent project will not normally be able to sync
with one another, since they are now separate projects with distinct
project codes. However, if the
"--from-parent-project" command-line option is provided to the
"[/help?cmd=pull|fossil pull]" command in the child, and the URL of
parent repository is also provided on the command-line, then updates to
the parent project that occurred after the child was created will be added
to the child repository. Thus, by periodically doing a
pull --from-parent-project, the child project is able to stay up to date
with all the latest changes in the parent.
|
Changes to www/mkindex.tcl.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 |
adding_code.wiki {Adding New Features To Fossil}
adding_code.wiki {Hacking Fossil}
antibot.wiki {Defense against Spiders and Bots}
blame.wiki {The Annotate/Blame Algorithm Of Fossil}
branching.wiki {Branching, Forking, Merging, and Tagging}
bugtheory.wiki {Bug Tracking In Fossil}
build.wiki {Compiling and Installing Fossil}
checkin_names.wiki {Check-in And Version Names}
checkin.wiki {Check-in Checklist}
| > | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
adding_code.wiki {Adding New Features To Fossil}
adding_code.wiki {Hacking Fossil}
antibot.wiki {Defense against Spiders and Bots}
blame.wiki {The Annotate/Blame Algorithm Of Fossil}
branching.wiki {Branching, Forking, Merging, and Tagging}
bugtheory.wiki {Bug Tracking In Fossil}
build.wiki {Compiling and Installing Fossil}
changes.wiki {Fossil Changelog}
checkin_names.wiki {Check-in And Version Names}
checkin.wiki {Check-in Checklist}
childprojects.wiki {Child Projects}
copyright-release.html {Contributor License Agreement}
concepts.wiki {Fossil Core Concepts}
contribute.wiki {Contributing Code or Documentation To The Fossil Project}
customgraph.md {Theming: Customizing the Timeline Graph}
customskin.md {Theming: Customizing The Appearance of Web Pages}
custom_ticket.wiki {Customizing The Ticket System}
delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm}
|
| ︙ | ︙ |
Changes to www/permutedindex.html.
| ︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <li><a href="changes.wiki">Changelog — Fossil</a></li> <li><a href="checkin_names.wiki">Check-in And Version Names</a></li> <li><a href="checkin.wiki">Check-in Checklist</a></li> <li><a href="checkin.wiki">Checklist — Check-in</a></li> <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> <li><a href="style.wiki">Code Style Guidelines — Source</a></li> <li><a href="build.wiki">Compiling and Installing Fossil</a></li> <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> | > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <li><a href="changes.wiki">Changelog — Fossil</a></li> <li><a href="checkin_names.wiki">Check-in And Version Names</a></li> <li><a href="checkin.wiki">Check-in Checklist</a></li> <li><a href="checkin.wiki">Checklist — Check-in</a></li> <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> <li><a href="childprojects.wiki">Child Projects</a></li> <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> <li><a href="style.wiki">Code Style Guidelines — Source</a></li> <li><a href="build.wiki">Compiling and Installing Fossil</a></li> <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> |
| ︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 | <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> <li><a href="pop.wiki">Principles Of Operations</a></li> <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> <li><a href="makefile.wiki">Process — The Fossil Build</a></li> <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> <li><a href="faq.wiki">Questions — Frequently Asked</a></li> <li><a href="qandc.wiki">Questions And Criticisms</a></li> <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> <li><a href="encryptedrepos.wiki">Repositories — How To Use Encrypted</a></li> | > | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | <li><a href="../test/release-checklist.wiki">Pre-Release Testing Checklist</a></li> <li><a href="pop.wiki">Principles Of Operations</a></li> <li><a href="private.wiki">Private Branches — Creating, Syncing, and Deleting</a></li> <li><a href="makefile.wiki">Process — The Fossil Build</a></li> <li><a href="contribute.wiki">Project — Contributing Code or Documentation To The Fossil</a></li> <li><a href="embeddeddoc.wiki">Project Documentation — Embedded</a></li> <li><a href="foss-cklist.wiki">Projects — Checklist For Successful Open-Source</a></li> <li><a href="childprojects.wiki">Projects — Child</a></li> <li><a href="sync.wiki">Protocol — The Fossil Sync</a></li> <li><a href="faq.wiki">Questions — Frequently Asked</a></li> <li><a href="qandc.wiki">Questions And Criticisms</a></li> <li><a href="quickstart.wiki">Quick Start Guide — Fossil</a></li> <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> <li><a href="encryptedrepos.wiki">Repositories — How To Use Encrypted</a></li> |
| ︙ | ︙ |