Fossil SCM
Merge-in styling improvements from trunk
Commit
bb159b9e96b035cc523fc279c0e0c4ad3e4bf63b2a2f68af441346969cde34e0
Parent
98b447109e9ef3e…
79 files changed
+1
-1
+219
-191
+1
-1
+14
-14
+5
-5
+2
-2
+3
-3
+4
-4
+1
-1
+2
-2
+2
-2
+67
-24
+1
-1
+5
-4
+2
-6
+1
-1
+1
-1
+2
-2
+9
-9
+4
-4
+1
-1
+2
-2
+3
-3
+6
-6
+1
-1
+16
-16
+2
-2
+1
-1
+4
-4
+2
-2
+1
-1
+6
-6
+1
-1
+1
-1
+1
-1
+1
-1
+1
-1
+7
-7
+5
-5
+6
-6
+15
-15
+7
-7
+7
-4
+3
-3
+1
-1
+6
-6
+2
-2
+57
-15
+1
-1
+7
-7
+1
-1
+26
-17
+2
-2
+2
-2
+1
-1
+4
-4
+11
-11
+3
-3
+2
-2
+49
+24
-2
+5
-5
+15
-15
+15
-15
+18
-15
+2
-2
+2
-2
+48
-40
+10
+1
-1
+33
+88
-35
+705
-202
+4
-4
+10
-1
+2
-1
+5
-4
+21
-1
+17
~
VERSION
~
skins/default/css.txt
~
skins/eagle/css.txt
~
src/alerts.c
~
src/attach.c
~
src/backlink.c
~
src/branch.c
~
src/browse.c
~
src/builtin.c
~
src/cache.c
~
src/captcha.c
~
src/clone.c
~
src/cookies.c
~
src/db.c
~
src/default.css
~
src/descendants.c
~
src/diff.c
~
src/dispatch.c
~
src/doc.c
~
src/event.c
~
src/extcgi.c
~
src/fileedit.c
~
src/finfo.c
~
src/forum.c
~
src/fossil.page.forumpost.js
~
src/info.c
~
src/interwiki.c
~
src/loadctrl.c
~
src/login.c
~
src/main.c
~
src/moderate.c
~
src/name.c
~
src/path.c
~
src/piechart.c
~
src/pikchrshow.c
~
src/printf.c
~
src/repolist.c
~
src/report.c
~
src/search.c
~
src/security_audit.c
~
src/setup.c
~
src/setupuser.c
~
src/shell.c
~
src/shun.c
~
src/sitemap.c
~
src/skins.c
~
src/smtp.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stat.c
~
src/statrep.c
~
src/style.c
~
src/tag.c
~
src/tar.c
~
src/th_main.c
~
src/timeline.c
~
src/tkt.c
~
src/tktsetup.c
~
src/unversioned.c
~
src/url.c
~
src/user.c
~
src/webmail.c
~
src/wiki.c
~
src/wiki.c
~
src/wikiformat.c
~
src/xfersetup.c
~
src/zip.c
~
www/backup.md
~
www/changes.wiki
~
www/checkin_names.wiki
~
www/ckout-workflows.md
~
www/fossil-v-git.wiki
~
www/gitusers.md
~
www/index.wiki
~
www/mirrortogithub.md
~
www/mkindex.tcl
~
www/permutedindex.html
~
www/serverext.wiki
~
www/shunning.wiki
M
VERSION
+1
-1
| --- VERSION | ||
| +++ VERSION | ||
| @@ -1,1 +1,1 @@ | ||
| 1 | -2.13 | |
| 1 | +2.14 | |
| 2 | 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 2.13 |
| 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 2.14 |
| 2 |
+219
-191
| --- skins/default/css.txt | ||
| +++ skins/default/css.txt | ||
| @@ -1,236 +1,264 @@ | ||
| 1 | +/* Overall page style */ | |
| 2 | + | |
| 1 | 3 | body { |
| 2 | - margin: 0 auto; | |
| 3 | - background-color: white; | |
| 4 | - font-family: sans-serif; | |
| 5 | - font-size:14pt; | |
| 6 | - -moz-text-size-adjust: none; | |
| 7 | - -webkit-text-size-adjust: none; | |
| 8 | - -mx-text-size-adjust: none; | |
| 4 | + margin: 0 auto; | |
| 5 | + background-color: white; | |
| 6 | + font-family: sans-serif; | |
| 7 | + font-size: 14pt; | |
| 8 | + -moz-text-size-adjust: none; | |
| 9 | + -mx-text-size-adjust: none; | |
| 10 | + -webkit-text-size-adjust: none; | |
| 9 | 11 | } |
| 10 | 12 | |
| 11 | 13 | a { |
| 12 | - color: #4183C4; | |
| 13 | - text-decoration: none; | |
| 14 | + color: #4183C4; | |
| 15 | + text-decoration: none; | |
| 14 | 16 | } |
| 15 | 17 | a:hover { |
| 16 | - color: #4183C4; | |
| 17 | - text-decoration: underline; | |
| 18 | -} | |
| 19 | -div.forumPosts a:visited { | |
| 20 | - color: #6A7F94; | |
| 18 | + color: #4183C4; | |
| 19 | + text-decoration: underline; | |
| 21 | 20 | } |
| 22 | 21 | |
| 23 | -hr { | |
| 24 | - color: #eee; | |
| 25 | -} | |
| 22 | + | |
| 23 | +/* Page title, above menu bars */ | |
| 26 | 24 | |
| 27 | 25 | .title { |
| 28 | - color: #4183C4; | |
| 29 | - float:left; | |
| 26 | + color: #4183C4; | |
| 27 | + float: left; | |
| 30 | 28 | } |
| 31 | 29 | .title h1 { |
| 32 | - display:inline; | |
| 30 | + display: inline; | |
| 33 | 31 | } |
| 34 | 32 | .title h1:after { |
| 35 | - content: " / "; | |
| 36 | - color: #777; | |
| 37 | - font-weight: normal; | |
| 38 | -} | |
| 39 | - | |
| 40 | -.content h1 { | |
| 41 | - font-size: 1.25em; | |
| 42 | -} | |
| 43 | -.content h2 { | |
| 44 | - font-size: 1.15em; | |
| 45 | -} | |
| 46 | -.content h3 { | |
| 47 | - font-size: 1.05em; | |
| 48 | - font-weight: bold; | |
| 49 | -} | |
| 50 | - | |
| 51 | -.section { | |
| 52 | - font-size: 1em; | |
| 53 | - font-weight: bold; | |
| 54 | - background-color: #f5f5f5; | |
| 55 | - border: 1px solid #d8d8d8; | |
| 56 | - border-radius: 3px 3px 0 0; | |
| 57 | - padding: 9px 10px 10px; | |
| 58 | - margin: 10px 0; | |
| 59 | -} | |
| 60 | - | |
| 61 | -.sectionmenu { | |
| 62 | - border: 1px solid #d8d8d8; | |
| 63 | - border-radius: 0 0 3px 3px; | |
| 64 | - border-top: 0; | |
| 65 | - margin-top: -10px; | |
| 66 | - margin-bottom: 10px; | |
| 67 | - padding: 10px; | |
| 68 | -} | |
| 69 | -.sectionmenu a { | |
| 70 | - display: inline-block; | |
| 71 | - margin-right: 1em; | |
| 72 | -} | |
| 73 | - | |
| 33 | + content: " / "; | |
| 34 | + color: #777; | |
| 35 | + font-weight: normal; | |
| 36 | +} | |
| 74 | 37 | .status { |
| 75 | - float:right; | |
| 76 | - font-size:.7em; | |
| 38 | + float: right; | |
| 39 | + font-size: 0.7em; | |
| 77 | 40 | } |
| 78 | 41 | |
| 42 | + | |
| 43 | +/* Main menu and optional sub-menu */ | |
| 44 | + | |
| 79 | 45 | .mainmenu { |
| 80 | - font-size:.8em; | |
| 81 | - clear:both; | |
| 82 | - background:#eaeaea linear-gradient(#fafafa, #eaeaea) repeat-x; | |
| 83 | - border:1px solid #eaeaea; | |
| 84 | - border-radius:5px; | |
| 85 | - overflow-x: auto; | |
| 86 | - overflow-y: hidden; | |
| 87 | - white-space: nowrap; | |
| 88 | - z-index: 21; /* just above hbdrop */ | |
| 89 | -} | |
| 90 | - | |
| 46 | + font-size: 0.8em; | |
| 47 | + clear: both; | |
| 48 | + background: #eaeaea linear-gradient(#fafafa, #eaeaea) repeat-x; | |
| 49 | + border: 1px solid #eaeaea; | |
| 50 | + border-radius: 5px; | |
| 51 | + overflow-x: auto; | |
| 52 | + overflow-y: hidden; | |
| 53 | + white-space: nowrap; | |
| 54 | + z-index: 21; /* just above hbdrop */ | |
| 55 | +} | |
| 91 | 56 | .mainmenu a { |
| 92 | - text-decoration:none; | |
| 93 | - color: #777; | |
| 94 | - border-right:1px solid #eaeaea; | |
| 57 | + text-decoration: none; | |
| 58 | + color: #777; | |
| 59 | + border-right: 1px solid #eaeaea; | |
| 95 | 60 | } |
| 96 | 61 | .mainmenu a.active, |
| 97 | 62 | .mainmenu a:hover { |
| 98 | - color: #000; | |
| 99 | - border-bottom:2px solid #D26911; | |
| 100 | -} | |
| 101 | - | |
| 102 | -div#hbdrop { | |
| 103 | - background-color: white; | |
| 104 | - border: 1px solid black; | |
| 105 | - border-top: white; | |
| 106 | - border-radius: 0 0 0.5em 0.5em; | |
| 107 | - display: none; | |
| 108 | - font-size: 80%; | |
| 109 | - left: 2em; | |
| 110 | - width: 90%; | |
| 111 | - padding-right: 1em; | |
| 112 | - position: absolute; | |
| 113 | - z-index: 20; /* just below mainmenu, but above timeline bubbles */ | |
| 63 | + color: #000; | |
| 64 | + border-bottom: 2px solid #D26911; | |
| 65 | +} | |
| 66 | +.mainmenu div#hbdrop { | |
| 67 | + background-color: white; | |
| 68 | + border: 1px solid black; | |
| 69 | + border-top: white; | |
| 70 | + border-radius: 0 0 0.5em 0.5em; | |
| 71 | + display: none; | |
| 72 | + font-size: 80%; | |
| 73 | + left: 2em; | |
| 74 | + width: 90%; | |
| 75 | + padding-right: 1em; | |
| 76 | + position: absolute; | |
| 77 | + z-index: 20; /* just below mainmenu, but above timeline bubbles */ | |
| 114 | 78 | } |
| 115 | 79 | |
| 116 | 80 | .submenu { |
| 117 | - font-size: .7em; | |
| 118 | - padding: 10px; | |
| 119 | - border-bottom: 1px solid #ccc; | |
| 81 | + font-size: .7em; | |
| 82 | + padding: 10px; | |
| 83 | + border-bottom: 1px solid #ccc; | |
| 120 | 84 | } |
| 121 | - | |
| 122 | 85 | .submenu a, .submenu label { |
| 123 | - padding: 10px 11px; | |
| 124 | - text-decoration:none; | |
| 125 | - color: #777; | |
| 86 | + padding: 10px 11px; | |
| 87 | + text-decoration: none; | |
| 88 | + color: #777; | |
| 126 | 89 | } |
| 127 | - | |
| 90 | +.submenu label { | |
| 91 | + white-space: nowrap; | |
| 92 | +} | |
| 128 | 93 | .submenu a:hover, .submenu label:hover { |
| 129 | - padding: 6px 10px; | |
| 130 | - border: 1px solid #ccc; | |
| 131 | - border-radius: 5px; | |
| 132 | - color: #000; | |
| 133 | -} | |
| 134 | - | |
| 135 | -.content { | |
| 136 | - padding-top: 10px; | |
| 137 | - font-size:.8em; | |
| 138 | - color: #444; | |
| 139 | -} | |
| 140 | - | |
| 141 | -.udiff, .sbsdiff { | |
| 142 | - font-size: .85em !important; | |
| 143 | - overflow: auto; | |
| 144 | - border: 1px solid #ccc; | |
| 145 | - border-radius: 5px; | |
| 146 | -} | |
| 147 | -.content blockquote { | |
| 148 | - padding: 0 15px; | |
| 149 | -} | |
| 150 | -div.forumHierRoot blockquote, div.forumHier blockquote, div.forumEdit blockquote, div.forumTime blockquote, div.forumTimeline blockquote { | |
| 151 | - background-color: rgba(65, 131, 196, 0.1); | |
| 152 | - border-left: 3px solid #254769; | |
| 153 | - padding: .1em 1em; | |
| 154 | -} | |
| 155 | - | |
| 156 | -table.report { | |
| 157 | - cursor: auto; | |
| 158 | - border-radius: 5px; | |
| 159 | - border: 1px solid #ccc; | |
| 160 | - margin: 1em 0; | |
| 161 | -} | |
| 162 | -.report td, .report th { | |
| 163 | - border: 0; | |
| 164 | - font-size: .8em; | |
| 165 | - padding: 10px; | |
| 166 | -} | |
| 167 | -.report td:first-child { | |
| 168 | - border-top-left-radius: 5px; | |
| 169 | -} | |
| 170 | -.report tbody tr:last-child td:first-child { | |
| 171 | - border-bottom-left-radius: 5px; | |
| 172 | -} | |
| 173 | -.report td:last-child { | |
| 174 | - border-top-right-radius: 5px; | |
| 175 | -} | |
| 176 | -.report tbody tr:last-child { | |
| 177 | - border-bottom-left-radius: 5px; | |
| 178 | - border-bottom-right-radius: 5px; | |
| 179 | -} | |
| 180 | -.report tbody tr:last-child td:last-child { | |
| 181 | - border-bottom-right-radius: 5px; | |
| 182 | -} | |
| 183 | -.report th { | |
| 184 | - cursor: pointer; | |
| 185 | -} | |
| 186 | -.report thead+tbody tr:hover { | |
| 187 | - background-color: #f5f9fc !important; | |
| 188 | -} | |
| 189 | - | |
| 190 | -td.tktDspLabel { | |
| 191 | - width: 70px; | |
| 192 | - text-align: right; | |
| 193 | - overflow: hidden; | |
| 194 | -} | |
| 195 | -td.tktDspValue { | |
| 196 | - text-align: left; | |
| 197 | - vertical-align: top; | |
| 198 | - background-color: #f8f8f8; | |
| 199 | - border: 1px solid #ccc; | |
| 200 | -} | |
| 201 | -td.tktDspValue pre { | |
| 202 | - white-space: pre-wrap; | |
| 203 | -} | |
| 204 | - | |
| 205 | -span.timelineDetail { | |
| 206 | - font-size: 90%; | |
| 207 | -} | |
| 208 | - | |
| 209 | -.footer { | |
| 210 | - border-top: 1px solid #ccc; | |
| 211 | - padding: 10px; | |
| 212 | - font-size:.7em; | |
| 213 | - margin-top: 10px; | |
| 214 | - color: #ccc; | |
| 215 | -} | |
| 216 | -div.timelineDate { | |
| 217 | - font-weight: bold; | |
| 218 | - white-space: nowrap; | |
| 94 | + padding: 6px 10px; | |
| 95 | + border: 1px solid #ccc; | |
| 96 | + border-radius: 5px; | |
| 97 | + color: #000; | |
| 219 | 98 | } |
| 220 | 99 | span.submenuctrl, span.submenuctrl input, select.submenuctrl { |
| 221 | 100 | color: #777; |
| 222 | 101 | } |
| 223 | 102 | span.submenuctrl { |
| 224 | 103 | white-space: nowrap; |
| 225 | 104 | } |
| 226 | -div.submenu label { | |
| 227 | - white-space: nowrap; | |
| 105 | + | |
| 106 | + | |
| 107 | +/* Main document area; elements common to most pages. */ | |
| 108 | + | |
| 109 | +.content { | |
| 110 | + padding-top: 10px; | |
| 111 | + font-size: 0.8em; | |
| 112 | + color: #444; | |
| 113 | +} | |
| 114 | +.content blockquote { | |
| 115 | + padding: 0 15px; | |
| 116 | +} | |
| 117 | +.content h1 { | |
| 118 | + font-size: 1.25em; | |
| 119 | +} | |
| 120 | +.content h2 { | |
| 121 | + font-size: 1.15em; | |
| 122 | +} | |
| 123 | +.content h3 { | |
| 124 | + font-size: 1.05em; | |
| 125 | +} | |
| 126 | + | |
| 127 | +.section { | |
| 128 | + font-size: 1em; | |
| 129 | + font-weight: bold; | |
| 130 | + background-color: #f5f5f5; | |
| 131 | + border: 1px solid #d8d8d8; | |
| 132 | + border-radius: 3px 3px 0 0; | |
| 133 | + padding: 9px 10px 10px; | |
| 134 | + margin: 10px 0; | |
| 135 | +} | |
| 136 | +.sectionmenu { | |
| 137 | + border: 1px solid #d8d8d8; | |
| 138 | + border-radius: 0 0 3px 3px; | |
| 139 | + border-top: 0; | |
| 140 | + margin-top: -10px; | |
| 141 | + margin-bottom: 10px; | |
| 142 | + padding: 10px; | |
| 143 | +} | |
| 144 | +.sectionmenu a { | |
| 145 | + display: inline-block; | |
| 146 | + margin-right: 1em; | |
| 147 | +} | |
| 148 | + | |
| 149 | +hr { | |
| 150 | + color: #eee; | |
| 151 | +} | |
| 152 | + | |
| 153 | + | |
| 154 | +/* Page footer */ | |
| 155 | + | |
| 156 | +.footer { | |
| 157 | + border-top: 1px solid #ccc; | |
| 158 | + padding: 10px; | |
| 159 | + font-size: 0.7em; | |
| 160 | + margin-top: 10px; | |
| 161 | + color: #ccc; | |
| 162 | +} | |
| 163 | + | |
| 164 | + | |
| 165 | +/* Exceptions for /info diff views */ | |
| 166 | + | |
| 167 | +.udiff, .sbsdiff { | |
| 168 | + font-size: .85em !important; | |
| 169 | + overflow: auto; | |
| 170 | + border: 1px solid #ccc; | |
| 171 | + border-radius: 5px; | |
| 172 | +} | |
| 173 | + | |
| 174 | + | |
| 175 | +/* Forum */ | |
| 176 | + | |
| 177 | +.forum a:visited { | |
| 178 | + color: #6A7F94; | |
| 179 | +} | |
| 180 | + | |
| 181 | +.forum blockquote { | |
| 182 | + background-color: rgba(65, 131, 196, 0.1); | |
| 183 | + border-left: 3px solid #254769; | |
| 184 | + padding: .1em 1em; | |
| 185 | +} | |
| 186 | + | |
| 187 | + | |
| 188 | +/* Tickets */ | |
| 189 | + | |
| 190 | +table.report { | |
| 191 | + cursor: auto; | |
| 192 | + border-radius: 5px; | |
| 193 | + border: 1px solid #ccc; | |
| 194 | + margin: 1em 0; | |
| 195 | +} | |
| 196 | +.report td, .report th { | |
| 197 | + border: 0; | |
| 198 | + font-size: .8em; | |
| 199 | + padding: 10px; | |
| 200 | +} | |
| 201 | +.report td:first-child { | |
| 202 | + border-top-left-radius: 5px; | |
| 203 | +} | |
| 204 | +.report tbody tr:last-child td:first-child { | |
| 205 | + border-bottom-left-radius: 5px; | |
| 206 | +} | |
| 207 | +.report td:last-child { | |
| 208 | + border-top-right-radius: 5px; | |
| 209 | +} | |
| 210 | +.report tbody tr:last-child { | |
| 211 | + border-bottom-left-radius: 5px; | |
| 212 | + border-bottom-right-radius: 5px; | |
| 213 | +} | |
| 214 | +.report tbody tr:last-child td:last-child { | |
| 215 | + border-bottom-right-radius: 5px; | |
| 216 | +} | |
| 217 | +.report th { | |
| 218 | + cursor: pointer; | |
| 219 | +} | |
| 220 | +.report thead+tbody tr:hover { | |
| 221 | + background-color: #f5f9fc !important; | |
| 222 | +} | |
| 223 | + | |
| 224 | +td.tktDspLabel { | |
| 225 | + width: 70px; | |
| 226 | + text-align: right; | |
| 227 | + overflow: hidden; | |
| 228 | +} | |
| 229 | +td.tktDspValue { | |
| 230 | + text-align: left; | |
| 231 | + vertical-align: top; | |
| 232 | + background-color: #f8f8f8; | |
| 233 | + border: 1px solid #ccc; | |
| 234 | +} | |
| 235 | +td.tktDspValue pre { | |
| 236 | + white-space: pre-wrap; | |
| 237 | +} | |
| 238 | + | |
| 239 | + | |
| 240 | +/* Timeline */ | |
| 241 | + | |
| 242 | +span.timelineDetail { | |
| 243 | + font-size: 90%; | |
| 244 | +} | |
| 245 | +div.timelineDate { | |
| 246 | + font-weight: bold; | |
| 247 | + white-space: nowrap; | |
| 228 | 248 | } |
| 249 | + | |
| 250 | + | |
| 251 | +/* Miscellaneous UI elements */ | |
| 252 | + | |
| 229 | 253 | .fossil-tooltip.help-buttonlet-content { |
| 230 | 254 | background-color: lightyellow; |
| 231 | 255 | } |
| 256 | + | |
| 257 | + | |
| 258 | +/* Exceptions for specific screen sizes */ | |
| 259 | + | |
| 232 | 260 | @media screen and (max-width: 600px) { |
| 233 | 261 | /* Spacing for mobile */ |
| 234 | 262 | body { |
| 235 | 263 | padding-left: 4px; |
| 236 | 264 | padding-right: 4px; |
| 237 | 265 |
| --- skins/default/css.txt | |
| +++ skins/default/css.txt | |
| @@ -1,236 +1,264 @@ | |
| 1 | body { |
| 2 | margin: 0 auto; |
| 3 | background-color: white; |
| 4 | font-family: sans-serif; |
| 5 | font-size:14pt; |
| 6 | -moz-text-size-adjust: none; |
| 7 | -webkit-text-size-adjust: none; |
| 8 | -mx-text-size-adjust: none; |
| 9 | } |
| 10 | |
| 11 | a { |
| 12 | color: #4183C4; |
| 13 | text-decoration: none; |
| 14 | } |
| 15 | a:hover { |
| 16 | color: #4183C4; |
| 17 | text-decoration: underline; |
| 18 | } |
| 19 | div.forumPosts a:visited { |
| 20 | color: #6A7F94; |
| 21 | } |
| 22 | |
| 23 | hr { |
| 24 | color: #eee; |
| 25 | } |
| 26 | |
| 27 | .title { |
| 28 | color: #4183C4; |
| 29 | float:left; |
| 30 | } |
| 31 | .title h1 { |
| 32 | display:inline; |
| 33 | } |
| 34 | .title h1:after { |
| 35 | content: " / "; |
| 36 | color: #777; |
| 37 | font-weight: normal; |
| 38 | } |
| 39 | |
| 40 | .content h1 { |
| 41 | font-size: 1.25em; |
| 42 | } |
| 43 | .content h2 { |
| 44 | font-size: 1.15em; |
| 45 | } |
| 46 | .content h3 { |
| 47 | font-size: 1.05em; |
| 48 | font-weight: bold; |
| 49 | } |
| 50 | |
| 51 | .section { |
| 52 | font-size: 1em; |
| 53 | font-weight: bold; |
| 54 | background-color: #f5f5f5; |
| 55 | border: 1px solid #d8d8d8; |
| 56 | border-radius: 3px 3px 0 0; |
| 57 | padding: 9px 10px 10px; |
| 58 | margin: 10px 0; |
| 59 | } |
| 60 | |
| 61 | .sectionmenu { |
| 62 | border: 1px solid #d8d8d8; |
| 63 | border-radius: 0 0 3px 3px; |
| 64 | border-top: 0; |
| 65 | margin-top: -10px; |
| 66 | margin-bottom: 10px; |
| 67 | padding: 10px; |
| 68 | } |
| 69 | .sectionmenu a { |
| 70 | display: inline-block; |
| 71 | margin-right: 1em; |
| 72 | } |
| 73 | |
| 74 | .status { |
| 75 | float:right; |
| 76 | font-size:.7em; |
| 77 | } |
| 78 | |
| 79 | .mainmenu { |
| 80 | font-size:.8em; |
| 81 | clear:both; |
| 82 | background:#eaeaea linear-gradient(#fafafa, #eaeaea) repeat-x; |
| 83 | border:1px solid #eaeaea; |
| 84 | border-radius:5px; |
| 85 | overflow-x: auto; |
| 86 | overflow-y: hidden; |
| 87 | white-space: nowrap; |
| 88 | z-index: 21; /* just above hbdrop */ |
| 89 | } |
| 90 | |
| 91 | .mainmenu a { |
| 92 | text-decoration:none; |
| 93 | color: #777; |
| 94 | border-right:1px solid #eaeaea; |
| 95 | } |
| 96 | .mainmenu a.active, |
| 97 | .mainmenu a:hover { |
| 98 | color: #000; |
| 99 | border-bottom:2px solid #D26911; |
| 100 | } |
| 101 | |
| 102 | div#hbdrop { |
| 103 | background-color: white; |
| 104 | border: 1px solid black; |
| 105 | border-top: white; |
| 106 | border-radius: 0 0 0.5em 0.5em; |
| 107 | display: none; |
| 108 | font-size: 80%; |
| 109 | left: 2em; |
| 110 | width: 90%; |
| 111 | padding-right: 1em; |
| 112 | position: absolute; |
| 113 | z-index: 20; /* just below mainmenu, but above timeline bubbles */ |
| 114 | } |
| 115 | |
| 116 | .submenu { |
| 117 | font-size: .7em; |
| 118 | padding: 10px; |
| 119 | border-bottom: 1px solid #ccc; |
| 120 | } |
| 121 | |
| 122 | .submenu a, .submenu label { |
| 123 | padding: 10px 11px; |
| 124 | text-decoration:none; |
| 125 | color: #777; |
| 126 | } |
| 127 | |
| 128 | .submenu a:hover, .submenu label:hover { |
| 129 | padding: 6px 10px; |
| 130 | border: 1px solid #ccc; |
| 131 | border-radius: 5px; |
| 132 | color: #000; |
| 133 | } |
| 134 | |
| 135 | .content { |
| 136 | padding-top: 10px; |
| 137 | font-size:.8em; |
| 138 | color: #444; |
| 139 | } |
| 140 | |
| 141 | .udiff, .sbsdiff { |
| 142 | font-size: .85em !important; |
| 143 | overflow: auto; |
| 144 | border: 1px solid #ccc; |
| 145 | border-radius: 5px; |
| 146 | } |
| 147 | .content blockquote { |
| 148 | padding: 0 15px; |
| 149 | } |
| 150 | div.forumHierRoot blockquote, div.forumHier blockquote, div.forumEdit blockquote, div.forumTime blockquote, div.forumTimeline blockquote { |
| 151 | background-color: rgba(65, 131, 196, 0.1); |
| 152 | border-left: 3px solid #254769; |
| 153 | padding: .1em 1em; |
| 154 | } |
| 155 | |
| 156 | table.report { |
| 157 | cursor: auto; |
| 158 | border-radius: 5px; |
| 159 | border: 1px solid #ccc; |
| 160 | margin: 1em 0; |
| 161 | } |
| 162 | .report td, .report th { |
| 163 | border: 0; |
| 164 | font-size: .8em; |
| 165 | padding: 10px; |
| 166 | } |
| 167 | .report td:first-child { |
| 168 | border-top-left-radius: 5px; |
| 169 | } |
| 170 | .report tbody tr:last-child td:first-child { |
| 171 | border-bottom-left-radius: 5px; |
| 172 | } |
| 173 | .report td:last-child { |
| 174 | border-top-right-radius: 5px; |
| 175 | } |
| 176 | .report tbody tr:last-child { |
| 177 | border-bottom-left-radius: 5px; |
| 178 | border-bottom-right-radius: 5px; |
| 179 | } |
| 180 | .report tbody tr:last-child td:last-child { |
| 181 | border-bottom-right-radius: 5px; |
| 182 | } |
| 183 | .report th { |
| 184 | cursor: pointer; |
| 185 | } |
| 186 | .report thead+tbody tr:hover { |
| 187 | background-color: #f5f9fc !important; |
| 188 | } |
| 189 | |
| 190 | td.tktDspLabel { |
| 191 | width: 70px; |
| 192 | text-align: right; |
| 193 | overflow: hidden; |
| 194 | } |
| 195 | td.tktDspValue { |
| 196 | text-align: left; |
| 197 | vertical-align: top; |
| 198 | background-color: #f8f8f8; |
| 199 | border: 1px solid #ccc; |
| 200 | } |
| 201 | td.tktDspValue pre { |
| 202 | white-space: pre-wrap; |
| 203 | } |
| 204 | |
| 205 | span.timelineDetail { |
| 206 | font-size: 90%; |
| 207 | } |
| 208 | |
| 209 | .footer { |
| 210 | border-top: 1px solid #ccc; |
| 211 | padding: 10px; |
| 212 | font-size:.7em; |
| 213 | margin-top: 10px; |
| 214 | color: #ccc; |
| 215 | } |
| 216 | div.timelineDate { |
| 217 | font-weight: bold; |
| 218 | white-space: nowrap; |
| 219 | } |
| 220 | span.submenuctrl, span.submenuctrl input, select.submenuctrl { |
| 221 | color: #777; |
| 222 | } |
| 223 | span.submenuctrl { |
| 224 | white-space: nowrap; |
| 225 | } |
| 226 | div.submenu label { |
| 227 | white-space: nowrap; |
| 228 | } |
| 229 | .fossil-tooltip.help-buttonlet-content { |
| 230 | background-color: lightyellow; |
| 231 | } |
| 232 | @media screen and (max-width: 600px) { |
| 233 | /* Spacing for mobile */ |
| 234 | body { |
| 235 | padding-left: 4px; |
| 236 | padding-right: 4px; |
| 237 |
| --- skins/default/css.txt | |
| +++ skins/default/css.txt | |
| @@ -1,236 +1,264 @@ | |
| 1 | /* Overall page style */ |
| 2 | |
| 3 | body { |
| 4 | margin: 0 auto; |
| 5 | background-color: white; |
| 6 | font-family: sans-serif; |
| 7 | font-size: 14pt; |
| 8 | -moz-text-size-adjust: none; |
| 9 | -mx-text-size-adjust: none; |
| 10 | -webkit-text-size-adjust: none; |
| 11 | } |
| 12 | |
| 13 | a { |
| 14 | color: #4183C4; |
| 15 | text-decoration: none; |
| 16 | } |
| 17 | a:hover { |
| 18 | color: #4183C4; |
| 19 | text-decoration: underline; |
| 20 | } |
| 21 | |
| 22 | |
| 23 | /* Page title, above menu bars */ |
| 24 | |
| 25 | .title { |
| 26 | color: #4183C4; |
| 27 | float: left; |
| 28 | } |
| 29 | .title h1 { |
| 30 | display: inline; |
| 31 | } |
| 32 | .title h1:after { |
| 33 | content: " / "; |
| 34 | color: #777; |
| 35 | font-weight: normal; |
| 36 | } |
| 37 | .status { |
| 38 | float: right; |
| 39 | font-size: 0.7em; |
| 40 | } |
| 41 | |
| 42 | |
| 43 | /* Main menu and optional sub-menu */ |
| 44 | |
| 45 | .mainmenu { |
| 46 | font-size: 0.8em; |
| 47 | clear: both; |
| 48 | background: #eaeaea linear-gradient(#fafafa, #eaeaea) repeat-x; |
| 49 | border: 1px solid #eaeaea; |
| 50 | border-radius: 5px; |
| 51 | overflow-x: auto; |
| 52 | overflow-y: hidden; |
| 53 | white-space: nowrap; |
| 54 | z-index: 21; /* just above hbdrop */ |
| 55 | } |
| 56 | .mainmenu a { |
| 57 | text-decoration: none; |
| 58 | color: #777; |
| 59 | border-right: 1px solid #eaeaea; |
| 60 | } |
| 61 | .mainmenu a.active, |
| 62 | .mainmenu a:hover { |
| 63 | color: #000; |
| 64 | border-bottom: 2px solid #D26911; |
| 65 | } |
| 66 | .mainmenu div#hbdrop { |
| 67 | background-color: white; |
| 68 | border: 1px solid black; |
| 69 | border-top: white; |
| 70 | border-radius: 0 0 0.5em 0.5em; |
| 71 | display: none; |
| 72 | font-size: 80%; |
| 73 | left: 2em; |
| 74 | width: 90%; |
| 75 | padding-right: 1em; |
| 76 | position: absolute; |
| 77 | z-index: 20; /* just below mainmenu, but above timeline bubbles */ |
| 78 | } |
| 79 | |
| 80 | .submenu { |
| 81 | font-size: .7em; |
| 82 | padding: 10px; |
| 83 | border-bottom: 1px solid #ccc; |
| 84 | } |
| 85 | .submenu a, .submenu label { |
| 86 | padding: 10px 11px; |
| 87 | text-decoration: none; |
| 88 | color: #777; |
| 89 | } |
| 90 | .submenu label { |
| 91 | white-space: nowrap; |
| 92 | } |
| 93 | .submenu a:hover, .submenu label:hover { |
| 94 | padding: 6px 10px; |
| 95 | border: 1px solid #ccc; |
| 96 | border-radius: 5px; |
| 97 | color: #000; |
| 98 | } |
| 99 | span.submenuctrl, span.submenuctrl input, select.submenuctrl { |
| 100 | color: #777; |
| 101 | } |
| 102 | span.submenuctrl { |
| 103 | white-space: nowrap; |
| 104 | } |
| 105 | |
| 106 | |
| 107 | /* Main document area; elements common to most pages. */ |
| 108 | |
| 109 | .content { |
| 110 | padding-top: 10px; |
| 111 | font-size: 0.8em; |
| 112 | color: #444; |
| 113 | } |
| 114 | .content blockquote { |
| 115 | padding: 0 15px; |
| 116 | } |
| 117 | .content h1 { |
| 118 | font-size: 1.25em; |
| 119 | } |
| 120 | .content h2 { |
| 121 | font-size: 1.15em; |
| 122 | } |
| 123 | .content h3 { |
| 124 | font-size: 1.05em; |
| 125 | } |
| 126 | |
| 127 | .section { |
| 128 | font-size: 1em; |
| 129 | font-weight: bold; |
| 130 | background-color: #f5f5f5; |
| 131 | border: 1px solid #d8d8d8; |
| 132 | border-radius: 3px 3px 0 0; |
| 133 | padding: 9px 10px 10px; |
| 134 | margin: 10px 0; |
| 135 | } |
| 136 | .sectionmenu { |
| 137 | border: 1px solid #d8d8d8; |
| 138 | border-radius: 0 0 3px 3px; |
| 139 | border-top: 0; |
| 140 | margin-top: -10px; |
| 141 | margin-bottom: 10px; |
| 142 | padding: 10px; |
| 143 | } |
| 144 | .sectionmenu a { |
| 145 | display: inline-block; |
| 146 | margin-right: 1em; |
| 147 | } |
| 148 | |
| 149 | hr { |
| 150 | color: #eee; |
| 151 | } |
| 152 | |
| 153 | |
| 154 | /* Page footer */ |
| 155 | |
| 156 | .footer { |
| 157 | border-top: 1px solid #ccc; |
| 158 | padding: 10px; |
| 159 | font-size: 0.7em; |
| 160 | margin-top: 10px; |
| 161 | color: #ccc; |
| 162 | } |
| 163 | |
| 164 | |
| 165 | /* Exceptions for /info diff views */ |
| 166 | |
| 167 | .udiff, .sbsdiff { |
| 168 | font-size: .85em !important; |
| 169 | overflow: auto; |
| 170 | border: 1px solid #ccc; |
| 171 | border-radius: 5px; |
| 172 | } |
| 173 | |
| 174 | |
| 175 | /* Forum */ |
| 176 | |
| 177 | .forum a:visited { |
| 178 | color: #6A7F94; |
| 179 | } |
| 180 | |
| 181 | .forum blockquote { |
| 182 | background-color: rgba(65, 131, 196, 0.1); |
| 183 | border-left: 3px solid #254769; |
| 184 | padding: .1em 1em; |
| 185 | } |
| 186 | |
| 187 | |
| 188 | /* Tickets */ |
| 189 | |
| 190 | table.report { |
| 191 | cursor: auto; |
| 192 | border-radius: 5px; |
| 193 | border: 1px solid #ccc; |
| 194 | margin: 1em 0; |
| 195 | } |
| 196 | .report td, .report th { |
| 197 | border: 0; |
| 198 | font-size: .8em; |
| 199 | padding: 10px; |
| 200 | } |
| 201 | .report td:first-child { |
| 202 | border-top-left-radius: 5px; |
| 203 | } |
| 204 | .report tbody tr:last-child td:first-child { |
| 205 | border-bottom-left-radius: 5px; |
| 206 | } |
| 207 | .report td:last-child { |
| 208 | border-top-right-radius: 5px; |
| 209 | } |
| 210 | .report tbody tr:last-child { |
| 211 | border-bottom-left-radius: 5px; |
| 212 | border-bottom-right-radius: 5px; |
| 213 | } |
| 214 | .report tbody tr:last-child td:last-child { |
| 215 | border-bottom-right-radius: 5px; |
| 216 | } |
| 217 | .report th { |
| 218 | cursor: pointer; |
| 219 | } |
| 220 | .report thead+tbody tr:hover { |
| 221 | background-color: #f5f9fc !important; |
| 222 | } |
| 223 | |
| 224 | td.tktDspLabel { |
| 225 | width: 70px; |
| 226 | text-align: right; |
| 227 | overflow: hidden; |
| 228 | } |
| 229 | td.tktDspValue { |
| 230 | text-align: left; |
| 231 | vertical-align: top; |
| 232 | background-color: #f8f8f8; |
| 233 | border: 1px solid #ccc; |
| 234 | } |
| 235 | td.tktDspValue pre { |
| 236 | white-space: pre-wrap; |
| 237 | } |
| 238 | |
| 239 | |
| 240 | /* Timeline */ |
| 241 | |
| 242 | span.timelineDetail { |
| 243 | font-size: 90%; |
| 244 | } |
| 245 | div.timelineDate { |
| 246 | font-weight: bold; |
| 247 | white-space: nowrap; |
| 248 | } |
| 249 | |
| 250 | |
| 251 | /* Miscellaneous UI elements */ |
| 252 | |
| 253 | .fossil-tooltip.help-buttonlet-content { |
| 254 | background-color: lightyellow; |
| 255 | } |
| 256 | |
| 257 | |
| 258 | /* Exceptions for specific screen sizes */ |
| 259 | |
| 260 | @media screen and (max-width: 600px) { |
| 261 | /* Spacing for mobile */ |
| 262 | body { |
| 263 | padding-left: 4px; |
| 264 | padding-right: 4px; |
| 265 |
+1
-1
| --- skins/eagle/css.txt | ||
| +++ skins/eagle/css.txt | ||
| @@ -381,11 +381,11 @@ | ||
| 381 | 381 | border: 1px solid white; |
| 382 | 382 | } |
| 383 | 383 | div.forumTimeline { |
| 384 | 384 | border: 1px solid white; |
| 385 | 385 | } |
| 386 | -div.forumHier, div.forumTime { | |
| 386 | +div.forumTime { | |
| 387 | 387 | border: 1px solid white; |
| 388 | 388 | } |
| 389 | 389 | div.forumSel { |
| 390 | 390 | background-color: #808080; |
| 391 | 391 | } |
| 392 | 392 |
| --- skins/eagle/css.txt | |
| +++ skins/eagle/css.txt | |
| @@ -381,11 +381,11 @@ | |
| 381 | border: 1px solid white; |
| 382 | } |
| 383 | div.forumTimeline { |
| 384 | border: 1px solid white; |
| 385 | } |
| 386 | div.forumHier, div.forumTime { |
| 387 | border: 1px solid white; |
| 388 | } |
| 389 | div.forumSel { |
| 390 | background-color: #808080; |
| 391 | } |
| 392 |
| --- skins/eagle/css.txt | |
| +++ skins/eagle/css.txt | |
| @@ -381,11 +381,11 @@ | |
| 381 | border: 1px solid white; |
| 382 | } |
| 383 | div.forumTimeline { |
| 384 | border: 1px solid white; |
| 385 | } |
| 386 | div.forumTime { |
| 387 | border: 1px solid white; |
| 388 | } |
| 389 | div.forumSel { |
| 390 | background-color: #808080; |
| 391 | } |
| 392 |
+14
-14
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -173,11 +173,11 @@ | ||
| 173 | 173 | */ |
| 174 | 174 | static int alert_webpages_disabled(void){ |
| 175 | 175 | if( alert_tables_exist() ) return 0; |
| 176 | 176 | style_header("Email Alerts Are Disabled"); |
| 177 | 177 | @ <p>Email alerts are disabled on this server</p> |
| 178 | - style_footer(); | |
| 178 | + style_finish_page("alerts"); | |
| 179 | 179 | return 1; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | /* |
| 183 | 183 | ** Insert a "Subscriber List" submenu link if the current user |
| @@ -308,11 +308,11 @@ | ||
| 308 | 308 | @ <hr> |
| 309 | 309 | |
| 310 | 310 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 311 | 311 | @ </div></form> |
| 312 | 312 | db_end_transaction(0); |
| 313 | - style_footer(); | |
| 313 | + style_finish_page("alerts"); | |
| 314 | 314 | } |
| 315 | 315 | |
| 316 | 316 | #if 0 |
| 317 | 317 | /* |
| 318 | 318 | ** Encode pMsg as MIME base64 and append it to pOut |
| @@ -1435,11 +1435,11 @@ | ||
| 1435 | 1435 | @ <p>An email has been sent to "%h(zEAddr)". That email contains a |
| 1436 | 1436 | @ hyperlink that you must click to activate your |
| 1437 | 1437 | @ subscription.</p> |
| 1438 | 1438 | } |
| 1439 | 1439 | alert_sender_free(pSender); |
| 1440 | - style_footer(); | |
| 1440 | + style_finish_page("alerts"); | |
| 1441 | 1441 | } |
| 1442 | 1442 | return; |
| 1443 | 1443 | } |
| 1444 | 1444 | style_header("Signup For Email Alerts"); |
| 1445 | 1445 | if( P("submit")==0 ){ |
| @@ -1552,11 +1552,11 @@ | ||
| 1552 | 1552 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 1553 | 1553 | @ </td></tr></table></div> |
| 1554 | 1554 | } |
| 1555 | 1555 | @ </form> |
| 1556 | 1556 | fossil_free(zErr); |
| 1557 | - style_footer(); | |
| 1557 | + style_finish_page("alerts"); | |
| 1558 | 1558 | } |
| 1559 | 1559 | |
| 1560 | 1560 | /* |
| 1561 | 1561 | ** Either shutdown or completely delete a subscription entry given |
| 1562 | 1562 | ** by the hex value zName. Then paint a webpage that explains that |
| @@ -1590,11 +1590,11 @@ | ||
| 1590 | 1590 | @ <a href="%R/setup_uedit?id=%d(uid)">edit or delete |
| 1591 | 1591 | @ the corresponding user "%h(zLogin)"</a></p> |
| 1592 | 1592 | } |
| 1593 | 1593 | } |
| 1594 | 1594 | db_finalize(&q); |
| 1595 | - style_footer(); | |
| 1595 | + style_finish_page("alerts"); | |
| 1596 | 1596 | return; |
| 1597 | 1597 | } |
| 1598 | 1598 | |
| 1599 | 1599 | /* |
| 1600 | 1600 | ** WEBPAGE: alerts |
| @@ -1914,11 +1914,11 @@ | ||
| 1914 | 1914 | @ </tr> |
| 1915 | 1915 | @ </table> |
| 1916 | 1916 | @ </form> |
| 1917 | 1917 | fossil_free(zErr); |
| 1918 | 1918 | db_finalize(&q); |
| 1919 | - style_footer(); | |
| 1919 | + style_finish_page("alerts"); | |
| 1920 | 1920 | db_commit_transaction(); |
| 1921 | 1921 | return; |
| 1922 | 1922 | } |
| 1923 | 1923 | |
| 1924 | 1924 | /* This is the message that gets sent to describe how to change |
| @@ -2021,11 +2021,11 @@ | ||
| 2021 | 2021 | }else{ |
| 2022 | 2022 | @ <p>An email has been sent to "%h(zEAddr)" that explains how to |
| 2023 | 2023 | @ unsubscribe and/or modify your subscription settings</p> |
| 2024 | 2024 | } |
| 2025 | 2025 | alert_sender_free(pSender); |
| 2026 | - style_footer(); | |
| 2026 | + style_finish_page("alerts"); | |
| 2027 | 2027 | return; |
| 2028 | 2028 | } |
| 2029 | 2029 | |
| 2030 | 2030 | /* Non-logged-in users have to enter an email address to which is |
| 2031 | 2031 | ** sent a message containing the unsubscribe link. |
| @@ -2071,11 +2071,11 @@ | ||
| 2071 | 2071 | @ </pre> |
| 2072 | 2072 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 2073 | 2073 | @ </td></tr></table></div> |
| 2074 | 2074 | @ </form> |
| 2075 | 2075 | fossil_free(zErr); |
| 2076 | - style_footer(); | |
| 2076 | + style_finish_page("alerts"); | |
| 2077 | 2077 | } |
| 2078 | 2078 | |
| 2079 | 2079 | /* |
| 2080 | 2080 | ** WEBPAGE: subscribers |
| 2081 | 2081 | ** |
| @@ -2182,11 +2182,11 @@ | ||
| 2182 | 2182 | @ </tr> |
| 2183 | 2183 | } |
| 2184 | 2184 | @ </tbody></table> |
| 2185 | 2185 | db_finalize(&q); |
| 2186 | 2186 | style_table_sorter(); |
| 2187 | - style_footer(); | |
| 2187 | + style_finish_page("alerts"); | |
| 2188 | 2188 | } |
| 2189 | 2189 | |
| 2190 | 2190 | #if LOCAL_INTERFACE |
| 2191 | 2191 | /* |
| 2192 | 2192 | ** A single event that might appear in an alert is recorded as an |
| @@ -2802,11 +2802,11 @@ | ||
| 2802 | 2802 | |
| 2803 | 2803 | login_check_credentials(); |
| 2804 | 2804 | if( zAdminEmail==0 || zAdminEmail[0]==0 ){ |
| 2805 | 2805 | style_header("Outbound Email Disabled"); |
| 2806 | 2806 | @ <p>Outbound email is disabled on this repository |
| 2807 | - style_footer(); | |
| 2807 | + style_finish_page("alerts"); | |
| 2808 | 2808 | return; |
| 2809 | 2809 | } |
| 2810 | 2810 | if( P("submit")!=0 |
| 2811 | 2811 | && P("subject")!=0 |
| 2812 | 2812 | && P("msg")!=0 |
| @@ -2834,11 +2834,11 @@ | ||
| 2834 | 2834 | }else{ |
| 2835 | 2835 | @ <p>Your message has been sent to the repository administrator. |
| 2836 | 2836 | @ Thank you for your input.</p> |
| 2837 | 2837 | } |
| 2838 | 2838 | alert_sender_free(pSender); |
| 2839 | - style_footer(); | |
| 2839 | + style_finish_page("alerts"); | |
| 2840 | 2840 | return; |
| 2841 | 2841 | } |
| 2842 | 2842 | if( captcha_needed() ){ |
| 2843 | 2843 | uSeed = captcha_seed(); |
| 2844 | 2844 | zDecoded = captcha_decode(uSeed); |
| @@ -2881,11 +2881,11 @@ | ||
| 2881 | 2881 | @ </pre> |
| 2882 | 2882 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 2883 | 2883 | @ </td></tr></table></div> |
| 2884 | 2884 | } |
| 2885 | 2885 | @ </form> |
| 2886 | - style_footer(); | |
| 2886 | + style_finish_page("alerts"); | |
| 2887 | 2887 | } |
| 2888 | 2888 | |
| 2889 | 2889 | /* |
| 2890 | 2890 | ** Send an annoucement message described by query parameter. |
| 2891 | 2891 | ** Permission to do this has already been verified. |
| @@ -2989,11 +2989,11 @@ | ||
| 2989 | 2989 | @ </pre></blockquote> |
| 2990 | 2990 | }else{ |
| 2991 | 2991 | @ <p>The announcement has been sent. |
| 2992 | 2992 | @ <a href="%h(PD("REQUEST_URI","/"))">Send another</a></p> |
| 2993 | 2993 | } |
| 2994 | - style_footer(); | |
| 2994 | + style_finish_page("alerts"); | |
| 2995 | 2995 | return; |
| 2996 | 2996 | } else if( !alert_enabled() ){ |
| 2997 | 2997 | style_header("Cannot Send Announcement"); |
| 2998 | 2998 | @ <p>Either you have no subscribers yet, or email alerts are not yet |
| 2999 | 2999 | @ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a> |
| @@ -3043,7 +3043,7 @@ | ||
| 3043 | 3043 | @ <td><input type="submit" name="submit" value="Send Message"> |
| 3044 | 3044 | } |
| 3045 | 3045 | @ </tr> |
| 3046 | 3046 | @ </table> |
| 3047 | 3047 | @ </form> |
| 3048 | - style_footer(); | |
| 3048 | + style_finish_page("alerts"); | |
| 3049 | 3049 | } |
| 3050 | 3050 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -173,11 +173,11 @@ | |
| 173 | */ |
| 174 | static int alert_webpages_disabled(void){ |
| 175 | if( alert_tables_exist() ) return 0; |
| 176 | style_header("Email Alerts Are Disabled"); |
| 177 | @ <p>Email alerts are disabled on this server</p> |
| 178 | style_footer(); |
| 179 | return 1; |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | ** Insert a "Subscriber List" submenu link if the current user |
| @@ -308,11 +308,11 @@ | |
| 308 | @ <hr> |
| 309 | |
| 310 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 311 | @ </div></form> |
| 312 | db_end_transaction(0); |
| 313 | style_footer(); |
| 314 | } |
| 315 | |
| 316 | #if 0 |
| 317 | /* |
| 318 | ** Encode pMsg as MIME base64 and append it to pOut |
| @@ -1435,11 +1435,11 @@ | |
| 1435 | @ <p>An email has been sent to "%h(zEAddr)". That email contains a |
| 1436 | @ hyperlink that you must click to activate your |
| 1437 | @ subscription.</p> |
| 1438 | } |
| 1439 | alert_sender_free(pSender); |
| 1440 | style_footer(); |
| 1441 | } |
| 1442 | return; |
| 1443 | } |
| 1444 | style_header("Signup For Email Alerts"); |
| 1445 | if( P("submit")==0 ){ |
| @@ -1552,11 +1552,11 @@ | |
| 1552 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 1553 | @ </td></tr></table></div> |
| 1554 | } |
| 1555 | @ </form> |
| 1556 | fossil_free(zErr); |
| 1557 | style_footer(); |
| 1558 | } |
| 1559 | |
| 1560 | /* |
| 1561 | ** Either shutdown or completely delete a subscription entry given |
| 1562 | ** by the hex value zName. Then paint a webpage that explains that |
| @@ -1590,11 +1590,11 @@ | |
| 1590 | @ <a href="%R/setup_uedit?id=%d(uid)">edit or delete |
| 1591 | @ the corresponding user "%h(zLogin)"</a></p> |
| 1592 | } |
| 1593 | } |
| 1594 | db_finalize(&q); |
| 1595 | style_footer(); |
| 1596 | return; |
| 1597 | } |
| 1598 | |
| 1599 | /* |
| 1600 | ** WEBPAGE: alerts |
| @@ -1914,11 +1914,11 @@ | |
| 1914 | @ </tr> |
| 1915 | @ </table> |
| 1916 | @ </form> |
| 1917 | fossil_free(zErr); |
| 1918 | db_finalize(&q); |
| 1919 | style_footer(); |
| 1920 | db_commit_transaction(); |
| 1921 | return; |
| 1922 | } |
| 1923 | |
| 1924 | /* This is the message that gets sent to describe how to change |
| @@ -2021,11 +2021,11 @@ | |
| 2021 | }else{ |
| 2022 | @ <p>An email has been sent to "%h(zEAddr)" that explains how to |
| 2023 | @ unsubscribe and/or modify your subscription settings</p> |
| 2024 | } |
| 2025 | alert_sender_free(pSender); |
| 2026 | style_footer(); |
| 2027 | return; |
| 2028 | } |
| 2029 | |
| 2030 | /* Non-logged-in users have to enter an email address to which is |
| 2031 | ** sent a message containing the unsubscribe link. |
| @@ -2071,11 +2071,11 @@ | |
| 2071 | @ </pre> |
| 2072 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 2073 | @ </td></tr></table></div> |
| 2074 | @ </form> |
| 2075 | fossil_free(zErr); |
| 2076 | style_footer(); |
| 2077 | } |
| 2078 | |
| 2079 | /* |
| 2080 | ** WEBPAGE: subscribers |
| 2081 | ** |
| @@ -2182,11 +2182,11 @@ | |
| 2182 | @ </tr> |
| 2183 | } |
| 2184 | @ </tbody></table> |
| 2185 | db_finalize(&q); |
| 2186 | style_table_sorter(); |
| 2187 | style_footer(); |
| 2188 | } |
| 2189 | |
| 2190 | #if LOCAL_INTERFACE |
| 2191 | /* |
| 2192 | ** A single event that might appear in an alert is recorded as an |
| @@ -2802,11 +2802,11 @@ | |
| 2802 | |
| 2803 | login_check_credentials(); |
| 2804 | if( zAdminEmail==0 || zAdminEmail[0]==0 ){ |
| 2805 | style_header("Outbound Email Disabled"); |
| 2806 | @ <p>Outbound email is disabled on this repository |
| 2807 | style_footer(); |
| 2808 | return; |
| 2809 | } |
| 2810 | if( P("submit")!=0 |
| 2811 | && P("subject")!=0 |
| 2812 | && P("msg")!=0 |
| @@ -2834,11 +2834,11 @@ | |
| 2834 | }else{ |
| 2835 | @ <p>Your message has been sent to the repository administrator. |
| 2836 | @ Thank you for your input.</p> |
| 2837 | } |
| 2838 | alert_sender_free(pSender); |
| 2839 | style_footer(); |
| 2840 | return; |
| 2841 | } |
| 2842 | if( captcha_needed() ){ |
| 2843 | uSeed = captcha_seed(); |
| 2844 | zDecoded = captcha_decode(uSeed); |
| @@ -2881,11 +2881,11 @@ | |
| 2881 | @ </pre> |
| 2882 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 2883 | @ </td></tr></table></div> |
| 2884 | } |
| 2885 | @ </form> |
| 2886 | style_footer(); |
| 2887 | } |
| 2888 | |
| 2889 | /* |
| 2890 | ** Send an annoucement message described by query parameter. |
| 2891 | ** Permission to do this has already been verified. |
| @@ -2989,11 +2989,11 @@ | |
| 2989 | @ </pre></blockquote> |
| 2990 | }else{ |
| 2991 | @ <p>The announcement has been sent. |
| 2992 | @ <a href="%h(PD("REQUEST_URI","/"))">Send another</a></p> |
| 2993 | } |
| 2994 | style_footer(); |
| 2995 | return; |
| 2996 | } else if( !alert_enabled() ){ |
| 2997 | style_header("Cannot Send Announcement"); |
| 2998 | @ <p>Either you have no subscribers yet, or email alerts are not yet |
| 2999 | @ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a> |
| @@ -3043,7 +3043,7 @@ | |
| 3043 | @ <td><input type="submit" name="submit" value="Send Message"> |
| 3044 | } |
| 3045 | @ </tr> |
| 3046 | @ </table> |
| 3047 | @ </form> |
| 3048 | style_footer(); |
| 3049 | } |
| 3050 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -173,11 +173,11 @@ | |
| 173 | */ |
| 174 | static int alert_webpages_disabled(void){ |
| 175 | if( alert_tables_exist() ) return 0; |
| 176 | style_header("Email Alerts Are Disabled"); |
| 177 | @ <p>Email alerts are disabled on this server</p> |
| 178 | style_finish_page("alerts"); |
| 179 | return 1; |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | ** Insert a "Subscriber List" submenu link if the current user |
| @@ -308,11 +308,11 @@ | |
| 308 | @ <hr> |
| 309 | |
| 310 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 311 | @ </div></form> |
| 312 | db_end_transaction(0); |
| 313 | style_finish_page("alerts"); |
| 314 | } |
| 315 | |
| 316 | #if 0 |
| 317 | /* |
| 318 | ** Encode pMsg as MIME base64 and append it to pOut |
| @@ -1435,11 +1435,11 @@ | |
| 1435 | @ <p>An email has been sent to "%h(zEAddr)". That email contains a |
| 1436 | @ hyperlink that you must click to activate your |
| 1437 | @ subscription.</p> |
| 1438 | } |
| 1439 | alert_sender_free(pSender); |
| 1440 | style_finish_page("alerts"); |
| 1441 | } |
| 1442 | return; |
| 1443 | } |
| 1444 | style_header("Signup For Email Alerts"); |
| 1445 | if( P("submit")==0 ){ |
| @@ -1552,11 +1552,11 @@ | |
| 1552 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 1553 | @ </td></tr></table></div> |
| 1554 | } |
| 1555 | @ </form> |
| 1556 | fossil_free(zErr); |
| 1557 | style_finish_page("alerts"); |
| 1558 | } |
| 1559 | |
| 1560 | /* |
| 1561 | ** Either shutdown or completely delete a subscription entry given |
| 1562 | ** by the hex value zName. Then paint a webpage that explains that |
| @@ -1590,11 +1590,11 @@ | |
| 1590 | @ <a href="%R/setup_uedit?id=%d(uid)">edit or delete |
| 1591 | @ the corresponding user "%h(zLogin)"</a></p> |
| 1592 | } |
| 1593 | } |
| 1594 | db_finalize(&q); |
| 1595 | style_finish_page("alerts"); |
| 1596 | return; |
| 1597 | } |
| 1598 | |
| 1599 | /* |
| 1600 | ** WEBPAGE: alerts |
| @@ -1914,11 +1914,11 @@ | |
| 1914 | @ </tr> |
| 1915 | @ </table> |
| 1916 | @ </form> |
| 1917 | fossil_free(zErr); |
| 1918 | db_finalize(&q); |
| 1919 | style_finish_page("alerts"); |
| 1920 | db_commit_transaction(); |
| 1921 | return; |
| 1922 | } |
| 1923 | |
| 1924 | /* This is the message that gets sent to describe how to change |
| @@ -2021,11 +2021,11 @@ | |
| 2021 | }else{ |
| 2022 | @ <p>An email has been sent to "%h(zEAddr)" that explains how to |
| 2023 | @ unsubscribe and/or modify your subscription settings</p> |
| 2024 | } |
| 2025 | alert_sender_free(pSender); |
| 2026 | style_finish_page("alerts"); |
| 2027 | return; |
| 2028 | } |
| 2029 | |
| 2030 | /* Non-logged-in users have to enter an email address to which is |
| 2031 | ** sent a message containing the unsubscribe link. |
| @@ -2071,11 +2071,11 @@ | |
| 2071 | @ </pre> |
| 2072 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 2073 | @ </td></tr></table></div> |
| 2074 | @ </form> |
| 2075 | fossil_free(zErr); |
| 2076 | style_finish_page("alerts"); |
| 2077 | } |
| 2078 | |
| 2079 | /* |
| 2080 | ** WEBPAGE: subscribers |
| 2081 | ** |
| @@ -2182,11 +2182,11 @@ | |
| 2182 | @ </tr> |
| 2183 | } |
| 2184 | @ </tbody></table> |
| 2185 | db_finalize(&q); |
| 2186 | style_table_sorter(); |
| 2187 | style_finish_page("alerts"); |
| 2188 | } |
| 2189 | |
| 2190 | #if LOCAL_INTERFACE |
| 2191 | /* |
| 2192 | ** A single event that might appear in an alert is recorded as an |
| @@ -2802,11 +2802,11 @@ | |
| 2802 | |
| 2803 | login_check_credentials(); |
| 2804 | if( zAdminEmail==0 || zAdminEmail[0]==0 ){ |
| 2805 | style_header("Outbound Email Disabled"); |
| 2806 | @ <p>Outbound email is disabled on this repository |
| 2807 | style_finish_page("alerts"); |
| 2808 | return; |
| 2809 | } |
| 2810 | if( P("submit")!=0 |
| 2811 | && P("subject")!=0 |
| 2812 | && P("msg")!=0 |
| @@ -2834,11 +2834,11 @@ | |
| 2834 | }else{ |
| 2835 | @ <p>Your message has been sent to the repository administrator. |
| 2836 | @ Thank you for your input.</p> |
| 2837 | } |
| 2838 | alert_sender_free(pSender); |
| 2839 | style_finish_page("alerts"); |
| 2840 | return; |
| 2841 | } |
| 2842 | if( captcha_needed() ){ |
| 2843 | uSeed = captcha_seed(); |
| 2844 | zDecoded = captcha_decode(uSeed); |
| @@ -2881,11 +2881,11 @@ | |
| 2881 | @ </pre> |
| 2882 | @ Enter the 8 characters above in the "Security Code" box<br/> |
| 2883 | @ </td></tr></table></div> |
| 2884 | } |
| 2885 | @ </form> |
| 2886 | style_finish_page("alerts"); |
| 2887 | } |
| 2888 | |
| 2889 | /* |
| 2890 | ** Send an annoucement message described by query parameter. |
| 2891 | ** Permission to do this has already been verified. |
| @@ -2989,11 +2989,11 @@ | |
| 2989 | @ </pre></blockquote> |
| 2990 | }else{ |
| 2991 | @ <p>The announcement has been sent. |
| 2992 | @ <a href="%h(PD("REQUEST_URI","/"))">Send another</a></p> |
| 2993 | } |
| 2994 | style_finish_page("alerts"); |
| 2995 | return; |
| 2996 | } else if( !alert_enabled() ){ |
| 2997 | style_header("Cannot Send Announcement"); |
| 2998 | @ <p>Either you have no subscribers yet, or email alerts are not yet |
| 2999 | @ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a> |
| @@ -3043,7 +3043,7 @@ | |
| 3043 | @ <td><input type="submit" name="submit" value="Send Message"> |
| 3044 | } |
| 3045 | @ </tr> |
| 3046 | @ </table> |
| 3047 | @ </form> |
| 3048 | style_finish_page("alerts"); |
| 3049 | } |
| 3050 |
+5
-5
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -145,11 +145,11 @@ | ||
| 145 | 145 | hyperlink_to_date(zDate, "."); |
| 146 | 146 | free(zUrlTail); |
| 147 | 147 | } |
| 148 | 148 | db_finalize(&q); |
| 149 | 149 | @ </ol> |
| 150 | - style_footer(); | |
| 150 | + style_finish_page("attach"); | |
| 151 | 151 | return; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | /* |
| 155 | 155 | ** WEBPAGE: attachdownload |
| @@ -205,16 +205,16 @@ | ||
| 205 | 205 | ); |
| 206 | 206 | } |
| 207 | 207 | if( zUUID==0 || zUUID[0]==0 ){ |
| 208 | 208 | style_header("No Such Attachment"); |
| 209 | 209 | @ No such attachment.... |
| 210 | - style_footer(); | |
| 210 | + style_finish_page("attach"); | |
| 211 | 211 | return; |
| 212 | 212 | }else if( zUUID[0]=='x' ){ |
| 213 | 213 | style_header("Missing"); |
| 214 | 214 | @ Attachment has been deleted |
| 215 | - style_footer(); | |
| 215 | + style_finish_page("attach"); | |
| 216 | 216 | return; |
| 217 | 217 | }else{ |
| 218 | 218 | g.perm.Read = 1; |
| 219 | 219 | cgi_replace_parameter("name",zUUID); |
| 220 | 220 | if( fossil_strcmp(g.zPath,"attachview")==0 ){ |
| @@ -410,11 +410,11 @@ | ||
| 410 | 410 | @ <input type="submit" name="ok" value="Add Attachment" /> |
| 411 | 411 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 412 | 412 | @ </div> |
| 413 | 413 | captcha_generate(0); |
| 414 | 414 | @ </form> |
| 415 | - style_footer(); | |
| 415 | + style_finish_page("attach"); | |
| 416 | 416 | fossil_free(zTargetType); |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | 419 | /* |
| 420 | 420 | ** WEBPAGE: ainfo |
| @@ -622,11 +622,11 @@ | ||
| 622 | 622 | @ <i>(file is %d(sz) bytes of binary data)</i> |
| 623 | 623 | } |
| 624 | 624 | @ </blockquote> |
| 625 | 625 | manifest_destroy(pAttach); |
| 626 | 626 | blob_reset(&attach); |
| 627 | - style_footer(); | |
| 627 | + style_finish_page("attach"); | |
| 628 | 628 | } |
| 629 | 629 | |
| 630 | 630 | /* |
| 631 | 631 | ** Output HTML to show a list of attachments. |
| 632 | 632 | */ |
| 633 | 633 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -145,11 +145,11 @@ | |
| 145 | hyperlink_to_date(zDate, "."); |
| 146 | free(zUrlTail); |
| 147 | } |
| 148 | db_finalize(&q); |
| 149 | @ </ol> |
| 150 | style_footer(); |
| 151 | return; |
| 152 | } |
| 153 | |
| 154 | /* |
| 155 | ** WEBPAGE: attachdownload |
| @@ -205,16 +205,16 @@ | |
| 205 | ); |
| 206 | } |
| 207 | if( zUUID==0 || zUUID[0]==0 ){ |
| 208 | style_header("No Such Attachment"); |
| 209 | @ No such attachment.... |
| 210 | style_footer(); |
| 211 | return; |
| 212 | }else if( zUUID[0]=='x' ){ |
| 213 | style_header("Missing"); |
| 214 | @ Attachment has been deleted |
| 215 | style_footer(); |
| 216 | return; |
| 217 | }else{ |
| 218 | g.perm.Read = 1; |
| 219 | cgi_replace_parameter("name",zUUID); |
| 220 | if( fossil_strcmp(g.zPath,"attachview")==0 ){ |
| @@ -410,11 +410,11 @@ | |
| 410 | @ <input type="submit" name="ok" value="Add Attachment" /> |
| 411 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 412 | @ </div> |
| 413 | captcha_generate(0); |
| 414 | @ </form> |
| 415 | style_footer(); |
| 416 | fossil_free(zTargetType); |
| 417 | } |
| 418 | |
| 419 | /* |
| 420 | ** WEBPAGE: ainfo |
| @@ -622,11 +622,11 @@ | |
| 622 | @ <i>(file is %d(sz) bytes of binary data)</i> |
| 623 | } |
| 624 | @ </blockquote> |
| 625 | manifest_destroy(pAttach); |
| 626 | blob_reset(&attach); |
| 627 | style_footer(); |
| 628 | } |
| 629 | |
| 630 | /* |
| 631 | ** Output HTML to show a list of attachments. |
| 632 | */ |
| 633 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -145,11 +145,11 @@ | |
| 145 | hyperlink_to_date(zDate, "."); |
| 146 | free(zUrlTail); |
| 147 | } |
| 148 | db_finalize(&q); |
| 149 | @ </ol> |
| 150 | style_finish_page("attach"); |
| 151 | return; |
| 152 | } |
| 153 | |
| 154 | /* |
| 155 | ** WEBPAGE: attachdownload |
| @@ -205,16 +205,16 @@ | |
| 205 | ); |
| 206 | } |
| 207 | if( zUUID==0 || zUUID[0]==0 ){ |
| 208 | style_header("No Such Attachment"); |
| 209 | @ No such attachment.... |
| 210 | style_finish_page("attach"); |
| 211 | return; |
| 212 | }else if( zUUID[0]=='x' ){ |
| 213 | style_header("Missing"); |
| 214 | @ Attachment has been deleted |
| 215 | style_finish_page("attach"); |
| 216 | return; |
| 217 | }else{ |
| 218 | g.perm.Read = 1; |
| 219 | cgi_replace_parameter("name",zUUID); |
| 220 | if( fossil_strcmp(g.zPath,"attachview")==0 ){ |
| @@ -410,11 +410,11 @@ | |
| 410 | @ <input type="submit" name="ok" value="Add Attachment" /> |
| 411 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 412 | @ </div> |
| 413 | captcha_generate(0); |
| 414 | @ </form> |
| 415 | style_finish_page("attach"); |
| 416 | fossil_free(zTargetType); |
| 417 | } |
| 418 | |
| 419 | /* |
| 420 | ** WEBPAGE: ainfo |
| @@ -622,11 +622,11 @@ | |
| 622 | @ <i>(file is %d(sz) bytes of binary data)</i> |
| 623 | } |
| 624 | @ </blockquote> |
| 625 | manifest_destroy(pAttach); |
| 626 | blob_reset(&attach); |
| 627 | style_finish_page("attach"); |
| 628 | } |
| 629 | |
| 630 | /* |
| 631 | ** Output HTML to show a list of attachments. |
| 632 | */ |
| 633 |
+2
-2
| --- src/backlink.c | ||
| +++ src/backlink.c | ||
| @@ -91,11 +91,11 @@ | ||
| 91 | 91 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 92 | 92 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 93 | 93 | www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL, |
| 94 | 94 | 0, 0, 0, 0, 0, 0); |
| 95 | 95 | db_finalize(&q); |
| 96 | - style_footer(); | |
| 96 | + style_finish_page("test"); | |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | /* |
| 100 | 100 | ** WEBPAGE: test-backlinks |
| 101 | 101 | ** |
| @@ -152,11 +152,11 @@ | ||
| 152 | 152 | @ <td>%h(zMtime)</tr> |
| 153 | 153 | } |
| 154 | 154 | @ </tbody> |
| 155 | 155 | @ </table> |
| 156 | 156 | db_finalize(&q); |
| 157 | - style_footer(); | |
| 157 | + style_finish_page("test"); | |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | /* |
| 161 | 161 | ** Remove all prior backlinks for the wiki page given. Then |
| 162 | 162 | ** add new backlinks for the latest version of the wiki page. |
| 163 | 163 |
| --- src/backlink.c | |
| +++ src/backlink.c | |
| @@ -91,11 +91,11 @@ | |
| 91 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 92 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 93 | www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL, |
| 94 | 0, 0, 0, 0, 0, 0); |
| 95 | db_finalize(&q); |
| 96 | style_footer(); |
| 97 | } |
| 98 | |
| 99 | /* |
| 100 | ** WEBPAGE: test-backlinks |
| 101 | ** |
| @@ -152,11 +152,11 @@ | |
| 152 | @ <td>%h(zMtime)</tr> |
| 153 | } |
| 154 | @ </tbody> |
| 155 | @ </table> |
| 156 | db_finalize(&q); |
| 157 | style_footer(); |
| 158 | } |
| 159 | |
| 160 | /* |
| 161 | ** Remove all prior backlinks for the wiki page given. Then |
| 162 | ** add new backlinks for the latest version of the wiki page. |
| 163 |
| --- src/backlink.c | |
| +++ src/backlink.c | |
| @@ -91,11 +91,11 @@ | |
| 91 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 92 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 93 | www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL, |
| 94 | 0, 0, 0, 0, 0, 0); |
| 95 | db_finalize(&q); |
| 96 | style_finish_page("test"); |
| 97 | } |
| 98 | |
| 99 | /* |
| 100 | ** WEBPAGE: test-backlinks |
| 101 | ** |
| @@ -152,11 +152,11 @@ | |
| 152 | @ <td>%h(zMtime)</tr> |
| 153 | } |
| 154 | @ </tbody> |
| 155 | @ </table> |
| 156 | db_finalize(&q); |
| 157 | style_finish_page("test"); |
| 158 | } |
| 159 | |
| 160 | /* |
| 161 | ** Remove all prior backlinks for the wiki page given. Then |
| 162 | ** add new backlinks for the latest version of the wiki page. |
| 163 |
+3
-3
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -514,11 +514,11 @@ | ||
| 514 | 514 | @ </tr> |
| 515 | 515 | } |
| 516 | 516 | @ </tbody></table></div> |
| 517 | 517 | db_finalize(&q); |
| 518 | 518 | style_table_sorter(); |
| 519 | - style_footer(); | |
| 519 | + style_finish_page("branch"); | |
| 520 | 520 | } |
| 521 | 521 | |
| 522 | 522 | /* |
| 523 | 523 | ** WEBPAGE: brlist |
| 524 | 524 | ** Show a list of branches. With no query parameters, a sortable table |
| @@ -622,11 +622,11 @@ | ||
| 622 | 622 | } |
| 623 | 623 | if( cnt ){ |
| 624 | 624 | @ </ul> |
| 625 | 625 | } |
| 626 | 626 | db_finalize(&q); |
| 627 | - style_footer(); | |
| 627 | + style_finish_page("branch"); | |
| 628 | 628 | } |
| 629 | 629 | |
| 630 | 630 | /* |
| 631 | 631 | ** This routine is called while for each check-in that is rendered by |
| 632 | 632 | ** the timeline of a "brlist" page. Add some additional hyperlinks |
| @@ -698,7 +698,7 @@ | ||
| 698 | 698 | if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH; |
| 699 | 699 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; |
| 700 | 700 | if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; |
| 701 | 701 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra); |
| 702 | 702 | db_finalize(&q); |
| 703 | - style_footer(); | |
| 703 | + style_finish_page("branch"); | |
| 704 | 704 | } |
| 705 | 705 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -514,11 +514,11 @@ | |
| 514 | @ </tr> |
| 515 | } |
| 516 | @ </tbody></table></div> |
| 517 | db_finalize(&q); |
| 518 | style_table_sorter(); |
| 519 | style_footer(); |
| 520 | } |
| 521 | |
| 522 | /* |
| 523 | ** WEBPAGE: brlist |
| 524 | ** Show a list of branches. With no query parameters, a sortable table |
| @@ -622,11 +622,11 @@ | |
| 622 | } |
| 623 | if( cnt ){ |
| 624 | @ </ul> |
| 625 | } |
| 626 | db_finalize(&q); |
| 627 | style_footer(); |
| 628 | } |
| 629 | |
| 630 | /* |
| 631 | ** This routine is called while for each check-in that is rendered by |
| 632 | ** the timeline of a "brlist" page. Add some additional hyperlinks |
| @@ -698,7 +698,7 @@ | |
| 698 | if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH; |
| 699 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; |
| 700 | if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; |
| 701 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra); |
| 702 | db_finalize(&q); |
| 703 | style_footer(); |
| 704 | } |
| 705 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -514,11 +514,11 @@ | |
| 514 | @ </tr> |
| 515 | } |
| 516 | @ </tbody></table></div> |
| 517 | db_finalize(&q); |
| 518 | style_table_sorter(); |
| 519 | style_finish_page("branch"); |
| 520 | } |
| 521 | |
| 522 | /* |
| 523 | ** WEBPAGE: brlist |
| 524 | ** Show a list of branches. With no query parameters, a sortable table |
| @@ -622,11 +622,11 @@ | |
| 622 | } |
| 623 | if( cnt ){ |
| 624 | @ </ul> |
| 625 | } |
| 626 | db_finalize(&q); |
| 627 | style_finish_page("branch"); |
| 628 | } |
| 629 | |
| 630 | /* |
| 631 | ** This routine is called while for each check-in that is rendered by |
| 632 | ** the timeline of a "brlist" page. Add some additional hyperlinks |
| @@ -698,7 +698,7 @@ | |
| 698 | if( PB("ng")==0 ) tmFlags |= TIMELINE_GRAPH; |
| 699 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; |
| 700 | if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; |
| 701 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, brtimeline_extra); |
| 702 | db_finalize(&q); |
| 703 | style_finish_page("branch"); |
| 704 | } |
| 705 |
+4
-4
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -336,11 +336,11 @@ | ||
| 336 | 336 | |
| 337 | 337 | /* If the "noreadme" query parameter is present, do not try to |
| 338 | 338 | ** show the content of the README file. |
| 339 | 339 | */ |
| 340 | 340 | if( P("noreadme")!=0 ){ |
| 341 | - style_footer(); | |
| 341 | + style_finish_page("dir"); | |
| 342 | 342 | return; |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | 345 | /* If the directory contains a readme file, then display its content below |
| 346 | 346 | ** the list of files |
| @@ -397,11 +397,11 @@ | ||
| 397 | 397 | document_emit_js(); |
| 398 | 398 | } |
| 399 | 399 | } |
| 400 | 400 | } |
| 401 | 401 | db_finalize(&q); |
| 402 | - style_footer(); | |
| 402 | + style_finish_page("dir"); | |
| 403 | 403 | } |
| 404 | 404 | |
| 405 | 405 | /* |
| 406 | 406 | ** Objects used by the "tree" webpage. |
| 407 | 407 | */ |
| @@ -913,11 +913,11 @@ | ||
| 913 | 913 | } |
| 914 | 914 | } |
| 915 | 915 | @ </ul> |
| 916 | 916 | @ </ul></div> |
| 917 | 917 | builtin_request_js("tree.js"); |
| 918 | - style_footer(); | |
| 918 | + style_finish_page("tree"); | |
| 919 | 919 | |
| 920 | 920 | /* We could free memory used by sTree here if we needed to. But |
| 921 | 921 | ** the process is about to exit, so doing so would not really accomplish |
| 922 | 922 | ** anything useful. */ |
| 923 | 923 | } |
| @@ -1167,7 +1167,7 @@ | ||
| 1167 | 1167 | fossil_free(zAge); |
| 1168 | 1168 | } |
| 1169 | 1169 | @ </table></div> |
| 1170 | 1170 | db_finalize(&q1); |
| 1171 | 1171 | db_finalize(&q2); |
| 1172 | - style_footer(); | |
| 1172 | + style_finish_page("fileage"); | |
| 1173 | 1173 | } |
| 1174 | 1174 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -336,11 +336,11 @@ | |
| 336 | |
| 337 | /* If the "noreadme" query parameter is present, do not try to |
| 338 | ** show the content of the README file. |
| 339 | */ |
| 340 | if( P("noreadme")!=0 ){ |
| 341 | style_footer(); |
| 342 | return; |
| 343 | } |
| 344 | |
| 345 | /* If the directory contains a readme file, then display its content below |
| 346 | ** the list of files |
| @@ -397,11 +397,11 @@ | |
| 397 | document_emit_js(); |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | db_finalize(&q); |
| 402 | style_footer(); |
| 403 | } |
| 404 | |
| 405 | /* |
| 406 | ** Objects used by the "tree" webpage. |
| 407 | */ |
| @@ -913,11 +913,11 @@ | |
| 913 | } |
| 914 | } |
| 915 | @ </ul> |
| 916 | @ </ul></div> |
| 917 | builtin_request_js("tree.js"); |
| 918 | style_footer(); |
| 919 | |
| 920 | /* We could free memory used by sTree here if we needed to. But |
| 921 | ** the process is about to exit, so doing so would not really accomplish |
| 922 | ** anything useful. */ |
| 923 | } |
| @@ -1167,7 +1167,7 @@ | |
| 1167 | fossil_free(zAge); |
| 1168 | } |
| 1169 | @ </table></div> |
| 1170 | db_finalize(&q1); |
| 1171 | db_finalize(&q2); |
| 1172 | style_footer(); |
| 1173 | } |
| 1174 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -336,11 +336,11 @@ | |
| 336 | |
| 337 | /* If the "noreadme" query parameter is present, do not try to |
| 338 | ** show the content of the README file. |
| 339 | */ |
| 340 | if( P("noreadme")!=0 ){ |
| 341 | style_finish_page("dir"); |
| 342 | return; |
| 343 | } |
| 344 | |
| 345 | /* If the directory contains a readme file, then display its content below |
| 346 | ** the list of files |
| @@ -397,11 +397,11 @@ | |
| 397 | document_emit_js(); |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | db_finalize(&q); |
| 402 | style_finish_page("dir"); |
| 403 | } |
| 404 | |
| 405 | /* |
| 406 | ** Objects used by the "tree" webpage. |
| 407 | */ |
| @@ -913,11 +913,11 @@ | |
| 913 | } |
| 914 | } |
| 915 | @ </ul> |
| 916 | @ </ul></div> |
| 917 | builtin_request_js("tree.js"); |
| 918 | style_finish_page("tree"); |
| 919 | |
| 920 | /* We could free memory used by sTree here if we needed to. But |
| 921 | ** the process is about to exit, so doing so would not really accomplish |
| 922 | ** anything useful. */ |
| 923 | } |
| @@ -1167,7 +1167,7 @@ | |
| 1167 | fossil_free(zAge); |
| 1168 | } |
| 1169 | @ </table></div> |
| 1170 | db_finalize(&q1); |
| 1171 | db_finalize(&q2); |
| 1172 | style_finish_page("fileage"); |
| 1173 | } |
| 1174 |
+1
-1
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -103,11 +103,11 @@ | ||
| 103 | 103 | char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain", |
| 104 | 104 | z,fossil_exe_id()); |
| 105 | 105 | @ <li>%z(zUrl)%h(z)</a> |
| 106 | 106 | } |
| 107 | 107 | @ </ol> |
| 108 | - style_footer(); | |
| 108 | + style_finish_page("test"); | |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | /* |
| 112 | 112 | ** COMMAND: test-builtin-get |
| 113 | 113 | ** |
| 114 | 114 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -103,11 +103,11 @@ | |
| 103 | char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain", |
| 104 | z,fossil_exe_id()); |
| 105 | @ <li>%z(zUrl)%h(z)</a> |
| 106 | } |
| 107 | @ </ol> |
| 108 | style_footer(); |
| 109 | } |
| 110 | |
| 111 | /* |
| 112 | ** COMMAND: test-builtin-get |
| 113 | ** |
| 114 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -103,11 +103,11 @@ | |
| 103 | char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain", |
| 104 | z,fossil_exe_id()); |
| 105 | @ <li>%z(zUrl)%h(z)</a> |
| 106 | } |
| 107 | @ </ol> |
| 108 | style_finish_page("test"); |
| 109 | } |
| 110 | |
| 111 | /* |
| 112 | ** COMMAND: test-builtin-get |
| 113 | ** |
| 114 |
+2
-2
| --- src/cache.c | ||
| +++ src/cache.c | ||
| @@ -384,11 +384,11 @@ | ||
| 384 | 384 | @ <p>cache-file name: %h(zDbName)</p> |
| 385 | 385 | @ <p>cache-file size: %s(zBuf)</p> |
| 386 | 386 | fossil_free(zDbName); |
| 387 | 387 | sqlite3_close(db); |
| 388 | 388 | } |
| 389 | - style_footer(); | |
| 389 | + style_finish_page("cache"); | |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | 392 | /* |
| 393 | 393 | ** WEBPAGE: cacheget |
| 394 | 394 | ** |
| @@ -407,11 +407,11 @@ | ||
| 407 | 407 | zKey = PD("key",""); |
| 408 | 408 | blob_zero(&content); |
| 409 | 409 | if( cache_read(&content, zKey)==0 ){ |
| 410 | 410 | style_header("Cache Download Error"); |
| 411 | 411 | @ The cache does not contain any entry with this key: "%h(zKey)" |
| 412 | - style_footer(); | |
| 412 | + style_finish_page("cache"); | |
| 413 | 413 | return; |
| 414 | 414 | } |
| 415 | 415 | cgi_set_content(&content); |
| 416 | 416 | cgi_set_content_type("application/x-compressed"); |
| 417 | 417 | } |
| 418 | 418 |
| --- src/cache.c | |
| +++ src/cache.c | |
| @@ -384,11 +384,11 @@ | |
| 384 | @ <p>cache-file name: %h(zDbName)</p> |
| 385 | @ <p>cache-file size: %s(zBuf)</p> |
| 386 | fossil_free(zDbName); |
| 387 | sqlite3_close(db); |
| 388 | } |
| 389 | style_footer(); |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | ** WEBPAGE: cacheget |
| 394 | ** |
| @@ -407,11 +407,11 @@ | |
| 407 | zKey = PD("key",""); |
| 408 | blob_zero(&content); |
| 409 | if( cache_read(&content, zKey)==0 ){ |
| 410 | style_header("Cache Download Error"); |
| 411 | @ The cache does not contain any entry with this key: "%h(zKey)" |
| 412 | style_footer(); |
| 413 | return; |
| 414 | } |
| 415 | cgi_set_content(&content); |
| 416 | cgi_set_content_type("application/x-compressed"); |
| 417 | } |
| 418 |
| --- src/cache.c | |
| +++ src/cache.c | |
| @@ -384,11 +384,11 @@ | |
| 384 | @ <p>cache-file name: %h(zDbName)</p> |
| 385 | @ <p>cache-file size: %s(zBuf)</p> |
| 386 | fossil_free(zDbName); |
| 387 | sqlite3_close(db); |
| 388 | } |
| 389 | style_finish_page("cache"); |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | ** WEBPAGE: cacheget |
| 394 | ** |
| @@ -407,11 +407,11 @@ | |
| 407 | zKey = PD("key",""); |
| 408 | blob_zero(&content); |
| 409 | if( cache_read(&content, zKey)==0 ){ |
| 410 | style_header("Cache Download Error"); |
| 411 | @ The cache does not contain any entry with this key: "%h(zKey)" |
| 412 | style_finish_page("cache"); |
| 413 | return; |
| 414 | } |
| 415 | cgi_set_content(&content); |
| 416 | cgi_set_content_type("application/x-compressed"); |
| 417 | } |
| 418 |
+2
-2
| --- src/captcha.c | ||
| +++ src/captcha.c | ||
| @@ -590,11 +590,11 @@ | ||
| 590 | 590 | } |
| 591 | 591 | style_header("Captcha Test"); |
| 592 | 592 | @ <pre> |
| 593 | 593 | @ %s(captcha_render(zPw)) |
| 594 | 594 | @ </pre> |
| 595 | - style_footer(); | |
| 595 | + style_finish_page("test"); | |
| 596 | 596 | } |
| 597 | 597 | |
| 598 | 598 | /* |
| 599 | 599 | ** Check to see if the current request is coming from an agent that might |
| 600 | 600 | ** be a spider. If the agent is not a spider, then return 0 without doing |
| @@ -627,11 +627,11 @@ | ||
| 627 | 627 | @ <form method='POST' action='%s(g.zPath)'> |
| 628 | 628 | cgi_query_parameters_to_hidden(); |
| 629 | 629 | @ <p>Please demonstrate that you are human, not a spider or robot</p> |
| 630 | 630 | captcha_generate(1); |
| 631 | 631 | @ </form> |
| 632 | - style_footer(); | |
| 632 | + style_finish_page("captcha"); | |
| 633 | 633 | return 1; |
| 634 | 634 | } |
| 635 | 635 | |
| 636 | 636 | /* |
| 637 | 637 | ** Generate a WAV file that reads aloud the hex digits given by |
| 638 | 638 |
| --- src/captcha.c | |
| +++ src/captcha.c | |
| @@ -590,11 +590,11 @@ | |
| 590 | } |
| 591 | style_header("Captcha Test"); |
| 592 | @ <pre> |
| 593 | @ %s(captcha_render(zPw)) |
| 594 | @ </pre> |
| 595 | style_footer(); |
| 596 | } |
| 597 | |
| 598 | /* |
| 599 | ** Check to see if the current request is coming from an agent that might |
| 600 | ** be a spider. If the agent is not a spider, then return 0 without doing |
| @@ -627,11 +627,11 @@ | |
| 627 | @ <form method='POST' action='%s(g.zPath)'> |
| 628 | cgi_query_parameters_to_hidden(); |
| 629 | @ <p>Please demonstrate that you are human, not a spider or robot</p> |
| 630 | captcha_generate(1); |
| 631 | @ </form> |
| 632 | style_footer(); |
| 633 | return 1; |
| 634 | } |
| 635 | |
| 636 | /* |
| 637 | ** Generate a WAV file that reads aloud the hex digits given by |
| 638 |
| --- src/captcha.c | |
| +++ src/captcha.c | |
| @@ -590,11 +590,11 @@ | |
| 590 | } |
| 591 | style_header("Captcha Test"); |
| 592 | @ <pre> |
| 593 | @ %s(captcha_render(zPw)) |
| 594 | @ </pre> |
| 595 | style_finish_page("test"); |
| 596 | } |
| 597 | |
| 598 | /* |
| 599 | ** Check to see if the current request is coming from an agent that might |
| 600 | ** be a spider. If the agent is not a spider, then return 0 without doing |
| @@ -627,11 +627,11 @@ | |
| 627 | @ <form method='POST' action='%s(g.zPath)'> |
| 628 | cgi_query_parameters_to_hidden(); |
| 629 | @ <p>Please demonstrate that you are human, not a spider or robot</p> |
| 630 | captcha_generate(1); |
| 631 | @ </form> |
| 632 | style_finish_page("captcha"); |
| 633 | return 1; |
| 634 | } |
| 635 | |
| 636 | /* |
| 637 | ** Generate a WAV file that reads aloud the hex digits given by |
| 638 |
+67
-24
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -80,15 +80,17 @@ | ||
| 80 | 80 | |
| 81 | 81 | |
| 82 | 82 | /* |
| 83 | 83 | ** COMMAND: clone |
| 84 | 84 | ** |
| 85 | -** Usage: %fossil clone ?OPTIONS? URI FILENAME | |
| 85 | +** Usage: %fossil clone ?OPTIONS? URI ?FILENAME? | |
| 86 | 86 | ** |
| 87 | 87 | ** Make a clone of a repository specified by URI in the local |
| 88 | -** file named FILENAME. URI may be one of the following forms: | |
| 89 | -** ([...] denotes optional elements): | |
| 88 | +** file named FILENAME. If FILENAME is omitted, then an appropriate | |
| 89 | +** filename is deduced from last element of the path in the URL. | |
| 90 | +** | |
| 91 | +** URI may be one of the following forms ([...] denotes optional elements): | |
| 90 | 92 | ** |
| 91 | 93 | ** * HTTP/HTTPS protocol: |
| 92 | 94 | ** |
| 93 | 95 | ** http[s]://[userid[:password]@]host[:port][/path] |
| 94 | 96 | ** |
| @@ -98,36 +100,43 @@ | ||
| 98 | 100 | ** |
| 99 | 101 | ** * Filesystem: |
| 100 | 102 | ** |
| 101 | 103 | ** [file://]path/to/repo.fossil |
| 102 | 104 | ** |
| 103 | -** Note that in Fossil (in contrast to some other DVCSes) a repository | |
| 104 | -** is distinct from a checkout. This command create a clone of a repository. | |
| 105 | -** Use the separate [[open]] command to open a checkout from that repository. | |
| 106 | -** | |
| 107 | 105 | ** For ssh and filesystem, path must have an extra leading |
| 108 | 106 | ** '/' to use an absolute path. |
| 109 | 107 | ** |
| 110 | 108 | ** Use %HH escapes for special characters in the userid and |
| 111 | 109 | ** password. For example "%40" in place of "@", "%2f" in place |
| 112 | 110 | ** of "/", and "%3a" in place of ":". |
| 111 | +** | |
| 112 | +** Note that in Fossil (in contrast to some other DVCSes) a repository | |
| 113 | +** is distinct from a checkout. Cloning a repository is not the same thing | |
| 114 | +** as opening a repository. This command always clones the repository. This | |
| 115 | +** command might also open the repository, but only if the --no-open option | |
| 116 | +** is omitted and either the --workdir option is included or the FILENAME | |
| 117 | +** argument is omitted. Use the separate [[open]] command to open a | |
| 118 | +** repository that was previously cloned and already exists on the | |
| 119 | +** local machine. | |
| 113 | 120 | ** |
| 114 | 121 | ** By default, the current login name is used to create the default |
| 115 | -** admin user. This can be overridden using the -A|--admin-user | |
| 116 | -** parameter. | |
| 122 | +** admin user for the new clone. This can be overridden using | |
| 123 | +** the -A|--admin-user parameter. | |
| 117 | 124 | ** |
| 118 | 125 | ** Options: |
| 119 | 126 | ** --admin-user|-A USERNAME Make USERNAME the administrator |
| 120 | 127 | ** --httpauth|-B USER:PASS Add HTTP Basic Authorization to requests |
| 121 | 128 | ** --nocompress Omit extra delta compression |
| 129 | +** --no-open Clone only. Do not open a check-out. | |
| 122 | 130 | ** --once Don't remember the URI. |
| 123 | 131 | ** --private Also clone private branches |
| 124 | 132 | ** --save-http-password Remember the HTTP password without asking |
| 125 | 133 | ** --ssh-command|-c SSH Use SSH as the "ssh" command |
| 126 | 134 | ** --ssl-identity FILENAME Use the SSL identity if requested by the server |
| 127 | 135 | ** -u|--unversioned Also sync unversioned content |
| 128 | 136 | ** -v|--verbose Show more statistics in output |
| 137 | +** --workdir DIR Also open a checkout in DIR | |
| 129 | 138 | ** |
| 130 | 139 | ** See also: [[init]], [[open]] |
| 131 | 140 | */ |
| 132 | 141 | void clone_cmd(void){ |
| 133 | 142 | char *zPassword; |
| @@ -135,10 +144,14 @@ | ||
| 135 | 144 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 136 | 145 | int nErr = 0; |
| 137 | 146 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 138 | 147 | int syncFlags = SYNC_CLONE; |
| 139 | 148 | int noCompress = find_option("nocompress",0,0)!=0; |
| 149 | + int noOpen = find_option("no-open",0,0)!=0; | |
| 150 | + const char *zRepo = 0; /* Name of the new local repository file */ | |
| 151 | + const char *zWorkDir = 0; /* Open in this director, if not zero */ | |
| 152 | + | |
| 140 | 153 | |
| 141 | 154 | /* Also clone private branches */ |
| 142 | 155 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 143 | 156 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 144 | 157 | if( find_option("save-http-password",0,0)!=0 ){ |
| @@ -147,49 +160,65 @@ | ||
| 147 | 160 | } |
| 148 | 161 | if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE; |
| 149 | 162 | if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED; |
| 150 | 163 | zHttpAuth = find_option("httpauth","B",1); |
| 151 | 164 | zDefaultUser = find_option("admin-user","A",1); |
| 165 | + zWorkDir = find_option("workdir", 0, 1); | |
| 152 | 166 | clone_ssh_find_options(); |
| 153 | 167 | url_proxy_options(); |
| 154 | 168 | |
| 155 | 169 | /* We should be done with options.. */ |
| 156 | 170 | verify_all_options(); |
| 157 | 171 | |
| 158 | - if( g.argc < 4 ){ | |
| 159 | - usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY"); | |
| 172 | + if( g.argc < 3 ){ | |
| 173 | + usage("?OPTIONS? FILE-OR-URL ?NEW-REPOSITORY?"); | |
| 160 | 174 | } |
| 161 | 175 | db_open_config(0, 0); |
| 162 | - if( -1 != file_size(g.argv[3], ExtFILE) ){ | |
| 163 | - fossil_fatal("file already exists: %s", g.argv[3]); | |
| 176 | + if( g.argc==4 ){ | |
| 177 | + zRepo = g.argv[3]; | |
| 178 | + }else{ | |
| 179 | + char *zBase = url_to_repo_basename(g.argv[2]); | |
| 180 | + if( zBase==0 ){ | |
| 181 | + fossil_fatal( | |
| 182 | + "unable to guess a repository name from the url \"%s\".\n" | |
| 183 | + "give the repository filename as an additional argument.", | |
| 184 | + g.argv[2]); | |
| 185 | + } | |
| 186 | + zRepo = mprintf("./%s.fossil", zBase); | |
| 187 | + if( zWorkDir==0 ){ | |
| 188 | + zWorkDir = mprintf("./%s", zBase); | |
| 189 | + } | |
| 190 | + fossil_free(zBase); | |
| 191 | + } | |
| 192 | + if( -1 != file_size(zRepo, ExtFILE) ){ | |
| 193 | + fossil_fatal("file already exists: %s", zRepo); | |
| 164 | 194 | } |
| 165 | - | |
| 166 | 195 | url_parse(g.argv[2], urlFlags); |
| 167 | 196 | if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; |
| 168 | 197 | if( g.url.isFile ){ |
| 169 | - file_copy(g.url.name, g.argv[3]); | |
| 198 | + file_copy(g.url.name, zRepo); | |
| 170 | 199 | db_close(1); |
| 171 | - db_open_repository(g.argv[3]); | |
| 200 | + db_open_repository(zRepo); | |
| 172 | 201 | db_open_config(1,0); |
| 173 | - db_record_repository_filename(g.argv[3]); | |
| 202 | + db_record_repository_filename(zRepo); | |
| 174 | 203 | url_remember(); |
| 175 | 204 | if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); |
| 176 | 205 | shun_artifacts(); |
| 177 | 206 | db_create_default_users(1, zDefaultUser); |
| 178 | 207 | if( zDefaultUser ){ |
| 179 | 208 | g.zLogin = zDefaultUser; |
| 180 | 209 | }else{ |
| 181 | 210 | g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'"); |
| 182 | 211 | } |
| 183 | - fossil_print("Repository cloned into %s\n", g.argv[3]); | |
| 212 | + fossil_print("Repository cloned into %s\n", zRepo); | |
| 184 | 213 | }else{ |
| 185 | 214 | db_close_config(); |
| 186 | - db_create_repository(g.argv[3]); | |
| 187 | - db_open_repository(g.argv[3]); | |
| 215 | + db_create_repository(zRepo); | |
| 216 | + db_open_repository(zRepo); | |
| 188 | 217 | db_open_config(0,0); |
| 189 | 218 | db_begin_transaction(); |
| 190 | - db_record_repository_filename(g.argv[3]); | |
| 219 | + db_record_repository_filename(zRepo); | |
| 191 | 220 | db_initial_setup(0, 0, zDefaultUser); |
| 192 | 221 | user_select(); |
| 193 | 222 | db_set("content-schema", CONTENT_SCHEMA, 0); |
| 194 | 223 | db_set("aux-schema", AUX_SCHEMA_MAX, 0); |
| 195 | 224 | db_set("rebuilt", get_version(), 0); |
| @@ -221,14 +250,14 @@ | ||
| 221 | 250 | g.xlinkClusterOnly = 0; |
| 222 | 251 | verify_cancel(); |
| 223 | 252 | db_end_transaction(0); |
| 224 | 253 | db_close(1); |
| 225 | 254 | if( nErr ){ |
| 226 | - file_delete(g.argv[3]); | |
| 255 | + file_delete(zRepo); | |
| 227 | 256 | fossil_fatal("server returned an error - clone aborted"); |
| 228 | 257 | } |
| 229 | - db_open_repository(g.argv[3]); | |
| 258 | + db_open_repository(zRepo); | |
| 230 | 259 | } |
| 231 | 260 | db_begin_transaction(); |
| 232 | 261 | fossil_print("Rebuilding repository meta-data...\n"); |
| 233 | 262 | rebuild_db(0, 1, 0); |
| 234 | 263 | if( !noCompress ){ |
| @@ -247,10 +276,24 @@ | ||
| 247 | 276 | db_protect_pop(); |
| 248 | 277 | fossil_print("\nproject-id: %s\n", db_get("project-code", 0)); |
| 249 | 278 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 250 | 279 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 251 | 280 | fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); |
| 281 | + if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ | |
| 282 | + char *azNew[6]; | |
| 283 | + fossil_print("opening the new %s repository in directory %s...\n", | |
| 284 | + zRepo, zWorkDir); | |
| 285 | + azNew[0] = g.argv[0]; | |
| 286 | + azNew[1] = "open"; | |
| 287 | + azNew[2] = (char*)zRepo; | |
| 288 | + azNew[3] = "--workdir"; | |
| 289 | + azNew[4] = (char*)zWorkDir; | |
| 290 | + azNew[5] = 0; | |
| 291 | + g.argv = azNew; | |
| 292 | + g.argc = 5; | |
| 293 | + cmd_open(); | |
| 294 | + } | |
| 252 | 295 | } |
| 253 | 296 | |
| 254 | 297 | /* |
| 255 | 298 | ** If user chooses to use HTTP Authentication over unencrypted HTTP, |
| 256 | 299 | ** remember decision. Otherwise, if the URL is being changed and no |
| @@ -363,7 +406,7 @@ | ||
| 363 | 406 | @ <p>Clone the repository using this command: |
| 364 | 407 | @ <blockquote><pre> |
| 365 | 408 | @ fossil clone %s(g.zBaseURL) %h(zNm).fossil |
| 366 | 409 | @ </pre></blockquote> |
| 367 | 410 | } |
| 368 | - style_footer(); | |
| 411 | + style_finish_page("download"); | |
| 369 | 412 | } |
| 370 | 413 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -80,15 +80,17 @@ | |
| 80 | |
| 81 | |
| 82 | /* |
| 83 | ** COMMAND: clone |
| 84 | ** |
| 85 | ** Usage: %fossil clone ?OPTIONS? URI FILENAME |
| 86 | ** |
| 87 | ** Make a clone of a repository specified by URI in the local |
| 88 | ** file named FILENAME. URI may be one of the following forms: |
| 89 | ** ([...] denotes optional elements): |
| 90 | ** |
| 91 | ** * HTTP/HTTPS protocol: |
| 92 | ** |
| 93 | ** http[s]://[userid[:password]@]host[:port][/path] |
| 94 | ** |
| @@ -98,36 +100,43 @@ | |
| 98 | ** |
| 99 | ** * Filesystem: |
| 100 | ** |
| 101 | ** [file://]path/to/repo.fossil |
| 102 | ** |
| 103 | ** Note that in Fossil (in contrast to some other DVCSes) a repository |
| 104 | ** is distinct from a checkout. This command create a clone of a repository. |
| 105 | ** Use the separate [[open]] command to open a checkout from that repository. |
| 106 | ** |
| 107 | ** For ssh and filesystem, path must have an extra leading |
| 108 | ** '/' to use an absolute path. |
| 109 | ** |
| 110 | ** Use %HH escapes for special characters in the userid and |
| 111 | ** password. For example "%40" in place of "@", "%2f" in place |
| 112 | ** of "/", and "%3a" in place of ":". |
| 113 | ** |
| 114 | ** By default, the current login name is used to create the default |
| 115 | ** admin user. This can be overridden using the -A|--admin-user |
| 116 | ** parameter. |
| 117 | ** |
| 118 | ** Options: |
| 119 | ** --admin-user|-A USERNAME Make USERNAME the administrator |
| 120 | ** --httpauth|-B USER:PASS Add HTTP Basic Authorization to requests |
| 121 | ** --nocompress Omit extra delta compression |
| 122 | ** --once Don't remember the URI. |
| 123 | ** --private Also clone private branches |
| 124 | ** --save-http-password Remember the HTTP password without asking |
| 125 | ** --ssh-command|-c SSH Use SSH as the "ssh" command |
| 126 | ** --ssl-identity FILENAME Use the SSL identity if requested by the server |
| 127 | ** -u|--unversioned Also sync unversioned content |
| 128 | ** -v|--verbose Show more statistics in output |
| 129 | ** |
| 130 | ** See also: [[init]], [[open]] |
| 131 | */ |
| 132 | void clone_cmd(void){ |
| 133 | char *zPassword; |
| @@ -135,10 +144,14 @@ | |
| 135 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 136 | int nErr = 0; |
| 137 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 138 | int syncFlags = SYNC_CLONE; |
| 139 | int noCompress = find_option("nocompress",0,0)!=0; |
| 140 | |
| 141 | /* Also clone private branches */ |
| 142 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 143 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 144 | if( find_option("save-http-password",0,0)!=0 ){ |
| @@ -147,49 +160,65 @@ | |
| 147 | } |
| 148 | if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE; |
| 149 | if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED; |
| 150 | zHttpAuth = find_option("httpauth","B",1); |
| 151 | zDefaultUser = find_option("admin-user","A",1); |
| 152 | clone_ssh_find_options(); |
| 153 | url_proxy_options(); |
| 154 | |
| 155 | /* We should be done with options.. */ |
| 156 | verify_all_options(); |
| 157 | |
| 158 | if( g.argc < 4 ){ |
| 159 | usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY"); |
| 160 | } |
| 161 | db_open_config(0, 0); |
| 162 | if( -1 != file_size(g.argv[3], ExtFILE) ){ |
| 163 | fossil_fatal("file already exists: %s", g.argv[3]); |
| 164 | } |
| 165 | |
| 166 | url_parse(g.argv[2], urlFlags); |
| 167 | if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; |
| 168 | if( g.url.isFile ){ |
| 169 | file_copy(g.url.name, g.argv[3]); |
| 170 | db_close(1); |
| 171 | db_open_repository(g.argv[3]); |
| 172 | db_open_config(1,0); |
| 173 | db_record_repository_filename(g.argv[3]); |
| 174 | url_remember(); |
| 175 | if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); |
| 176 | shun_artifacts(); |
| 177 | db_create_default_users(1, zDefaultUser); |
| 178 | if( zDefaultUser ){ |
| 179 | g.zLogin = zDefaultUser; |
| 180 | }else{ |
| 181 | g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'"); |
| 182 | } |
| 183 | fossil_print("Repository cloned into %s\n", g.argv[3]); |
| 184 | }else{ |
| 185 | db_close_config(); |
| 186 | db_create_repository(g.argv[3]); |
| 187 | db_open_repository(g.argv[3]); |
| 188 | db_open_config(0,0); |
| 189 | db_begin_transaction(); |
| 190 | db_record_repository_filename(g.argv[3]); |
| 191 | db_initial_setup(0, 0, zDefaultUser); |
| 192 | user_select(); |
| 193 | db_set("content-schema", CONTENT_SCHEMA, 0); |
| 194 | db_set("aux-schema", AUX_SCHEMA_MAX, 0); |
| 195 | db_set("rebuilt", get_version(), 0); |
| @@ -221,14 +250,14 @@ | |
| 221 | g.xlinkClusterOnly = 0; |
| 222 | verify_cancel(); |
| 223 | db_end_transaction(0); |
| 224 | db_close(1); |
| 225 | if( nErr ){ |
| 226 | file_delete(g.argv[3]); |
| 227 | fossil_fatal("server returned an error - clone aborted"); |
| 228 | } |
| 229 | db_open_repository(g.argv[3]); |
| 230 | } |
| 231 | db_begin_transaction(); |
| 232 | fossil_print("Rebuilding repository meta-data...\n"); |
| 233 | rebuild_db(0, 1, 0); |
| 234 | if( !noCompress ){ |
| @@ -247,10 +276,24 @@ | |
| 247 | db_protect_pop(); |
| 248 | fossil_print("\nproject-id: %s\n", db_get("project-code", 0)); |
| 249 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 250 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 251 | fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); |
| 252 | } |
| 253 | |
| 254 | /* |
| 255 | ** If user chooses to use HTTP Authentication over unencrypted HTTP, |
| 256 | ** remember decision. Otherwise, if the URL is being changed and no |
| @@ -363,7 +406,7 @@ | |
| 363 | @ <p>Clone the repository using this command: |
| 364 | @ <blockquote><pre> |
| 365 | @ fossil clone %s(g.zBaseURL) %h(zNm).fossil |
| 366 | @ </pre></blockquote> |
| 367 | } |
| 368 | style_footer(); |
| 369 | } |
| 370 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -80,15 +80,17 @@ | |
| 80 | |
| 81 | |
| 82 | /* |
| 83 | ** COMMAND: clone |
| 84 | ** |
| 85 | ** Usage: %fossil clone ?OPTIONS? URI ?FILENAME? |
| 86 | ** |
| 87 | ** Make a clone of a repository specified by URI in the local |
| 88 | ** file named FILENAME. If FILENAME is omitted, then an appropriate |
| 89 | ** filename is deduced from last element of the path in the URL. |
| 90 | ** |
| 91 | ** URI may be one of the following forms ([...] denotes optional elements): |
| 92 | ** |
| 93 | ** * HTTP/HTTPS protocol: |
| 94 | ** |
| 95 | ** http[s]://[userid[:password]@]host[:port][/path] |
| 96 | ** |
| @@ -98,36 +100,43 @@ | |
| 100 | ** |
| 101 | ** * Filesystem: |
| 102 | ** |
| 103 | ** [file://]path/to/repo.fossil |
| 104 | ** |
| 105 | ** For ssh and filesystem, path must have an extra leading |
| 106 | ** '/' to use an absolute path. |
| 107 | ** |
| 108 | ** Use %HH escapes for special characters in the userid and |
| 109 | ** password. For example "%40" in place of "@", "%2f" in place |
| 110 | ** of "/", and "%3a" in place of ":". |
| 111 | ** |
| 112 | ** Note that in Fossil (in contrast to some other DVCSes) a repository |
| 113 | ** is distinct from a checkout. Cloning a repository is not the same thing |
| 114 | ** as opening a repository. This command always clones the repository. This |
| 115 | ** command might also open the repository, but only if the --no-open option |
| 116 | ** is omitted and either the --workdir option is included or the FILENAME |
| 117 | ** argument is omitted. Use the separate [[open]] command to open a |
| 118 | ** repository that was previously cloned and already exists on the |
| 119 | ** local machine. |
| 120 | ** |
| 121 | ** By default, the current login name is used to create the default |
| 122 | ** admin user for the new clone. This can be overridden using |
| 123 | ** the -A|--admin-user parameter. |
| 124 | ** |
| 125 | ** Options: |
| 126 | ** --admin-user|-A USERNAME Make USERNAME the administrator |
| 127 | ** --httpauth|-B USER:PASS Add HTTP Basic Authorization to requests |
| 128 | ** --nocompress Omit extra delta compression |
| 129 | ** --no-open Clone only. Do not open a check-out. |
| 130 | ** --once Don't remember the URI. |
| 131 | ** --private Also clone private branches |
| 132 | ** --save-http-password Remember the HTTP password without asking |
| 133 | ** --ssh-command|-c SSH Use SSH as the "ssh" command |
| 134 | ** --ssl-identity FILENAME Use the SSL identity if requested by the server |
| 135 | ** -u|--unversioned Also sync unversioned content |
| 136 | ** -v|--verbose Show more statistics in output |
| 137 | ** --workdir DIR Also open a checkout in DIR |
| 138 | ** |
| 139 | ** See also: [[init]], [[open]] |
| 140 | */ |
| 141 | void clone_cmd(void){ |
| 142 | char *zPassword; |
| @@ -135,10 +144,14 @@ | |
| 144 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 145 | int nErr = 0; |
| 146 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 147 | int syncFlags = SYNC_CLONE; |
| 148 | int noCompress = find_option("nocompress",0,0)!=0; |
| 149 | int noOpen = find_option("no-open",0,0)!=0; |
| 150 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 151 | const char *zWorkDir = 0; /* Open in this director, if not zero */ |
| 152 | |
| 153 | |
| 154 | /* Also clone private branches */ |
| 155 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 156 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 157 | if( find_option("save-http-password",0,0)!=0 ){ |
| @@ -147,49 +160,65 @@ | |
| 160 | } |
| 161 | if( find_option("verbose","v",0)!=0) syncFlags |= SYNC_VERBOSE; |
| 162 | if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED; |
| 163 | zHttpAuth = find_option("httpauth","B",1); |
| 164 | zDefaultUser = find_option("admin-user","A",1); |
| 165 | zWorkDir = find_option("workdir", 0, 1); |
| 166 | clone_ssh_find_options(); |
| 167 | url_proxy_options(); |
| 168 | |
| 169 | /* We should be done with options.. */ |
| 170 | verify_all_options(); |
| 171 | |
| 172 | if( g.argc < 3 ){ |
| 173 | usage("?OPTIONS? FILE-OR-URL ?NEW-REPOSITORY?"); |
| 174 | } |
| 175 | db_open_config(0, 0); |
| 176 | if( g.argc==4 ){ |
| 177 | zRepo = g.argv[3]; |
| 178 | }else{ |
| 179 | char *zBase = url_to_repo_basename(g.argv[2]); |
| 180 | if( zBase==0 ){ |
| 181 | fossil_fatal( |
| 182 | "unable to guess a repository name from the url \"%s\".\n" |
| 183 | "give the repository filename as an additional argument.", |
| 184 | g.argv[2]); |
| 185 | } |
| 186 | zRepo = mprintf("./%s.fossil", zBase); |
| 187 | if( zWorkDir==0 ){ |
| 188 | zWorkDir = mprintf("./%s", zBase); |
| 189 | } |
| 190 | fossil_free(zBase); |
| 191 | } |
| 192 | if( -1 != file_size(zRepo, ExtFILE) ){ |
| 193 | fossil_fatal("file already exists: %s", zRepo); |
| 194 | } |
| 195 | url_parse(g.argv[2], urlFlags); |
| 196 | if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; |
| 197 | if( g.url.isFile ){ |
| 198 | file_copy(g.url.name, zRepo); |
| 199 | db_close(1); |
| 200 | db_open_repository(zRepo); |
| 201 | db_open_config(1,0); |
| 202 | db_record_repository_filename(zRepo); |
| 203 | url_remember(); |
| 204 | if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); |
| 205 | shun_artifacts(); |
| 206 | db_create_default_users(1, zDefaultUser); |
| 207 | if( zDefaultUser ){ |
| 208 | g.zLogin = zDefaultUser; |
| 209 | }else{ |
| 210 | g.zLogin = db_text(0, "SELECT login FROM user WHERE cap LIKE '%%s%%'"); |
| 211 | } |
| 212 | fossil_print("Repository cloned into %s\n", zRepo); |
| 213 | }else{ |
| 214 | db_close_config(); |
| 215 | db_create_repository(zRepo); |
| 216 | db_open_repository(zRepo); |
| 217 | db_open_config(0,0); |
| 218 | db_begin_transaction(); |
| 219 | db_record_repository_filename(zRepo); |
| 220 | db_initial_setup(0, 0, zDefaultUser); |
| 221 | user_select(); |
| 222 | db_set("content-schema", CONTENT_SCHEMA, 0); |
| 223 | db_set("aux-schema", AUX_SCHEMA_MAX, 0); |
| 224 | db_set("rebuilt", get_version(), 0); |
| @@ -221,14 +250,14 @@ | |
| 250 | g.xlinkClusterOnly = 0; |
| 251 | verify_cancel(); |
| 252 | db_end_transaction(0); |
| 253 | db_close(1); |
| 254 | if( nErr ){ |
| 255 | file_delete(zRepo); |
| 256 | fossil_fatal("server returned an error - clone aborted"); |
| 257 | } |
| 258 | db_open_repository(zRepo); |
| 259 | } |
| 260 | db_begin_transaction(); |
| 261 | fossil_print("Rebuilding repository meta-data...\n"); |
| 262 | rebuild_db(0, 1, 0); |
| 263 | if( !noCompress ){ |
| @@ -247,10 +276,24 @@ | |
| 276 | db_protect_pop(); |
| 277 | fossil_print("\nproject-id: %s\n", db_get("project-code", 0)); |
| 278 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 279 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 280 | fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); |
| 281 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 282 | char *azNew[6]; |
| 283 | fossil_print("opening the new %s repository in directory %s...\n", |
| 284 | zRepo, zWorkDir); |
| 285 | azNew[0] = g.argv[0]; |
| 286 | azNew[1] = "open"; |
| 287 | azNew[2] = (char*)zRepo; |
| 288 | azNew[3] = "--workdir"; |
| 289 | azNew[4] = (char*)zWorkDir; |
| 290 | azNew[5] = 0; |
| 291 | g.argv = azNew; |
| 292 | g.argc = 5; |
| 293 | cmd_open(); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | ** If user chooses to use HTTP Authentication over unencrypted HTTP, |
| 299 | ** remember decision. Otherwise, if the URL is being changed and no |
| @@ -363,7 +406,7 @@ | |
| 406 | @ <p>Clone the repository using this command: |
| 407 | @ <blockquote><pre> |
| 408 | @ fossil clone %s(g.zBaseURL) %h(zNm).fossil |
| 409 | @ </pre></blockquote> |
| 410 | } |
| 411 | style_finish_page("download"); |
| 412 | } |
| 413 |
+1
-1
| --- src/cookies.c | ||
| +++ src/cookies.c | ||
| @@ -225,7 +225,7 @@ | ||
| 225 | 225 | @ <li>Raw cookie value: "%h(PD("fossil_display_settings",""))" |
| 226 | 226 | for(i=0; i<cookies.nParam; i++){ |
| 227 | 227 | @ <li>%h(cookies.aParam[i].zPName): "%h(cookies.aParam[i].zPValue)" |
| 228 | 228 | } |
| 229 | 229 | @ </ul> |
| 230 | - style_footer(); | |
| 230 | + style_finish_page("cookies"); | |
| 231 | 231 | } |
| 232 | 232 |
| --- src/cookies.c | |
| +++ src/cookies.c | |
| @@ -225,7 +225,7 @@ | |
| 225 | @ <li>Raw cookie value: "%h(PD("fossil_display_settings",""))" |
| 226 | for(i=0; i<cookies.nParam; i++){ |
| 227 | @ <li>%h(cookies.aParam[i].zPName): "%h(cookies.aParam[i].zPValue)" |
| 228 | } |
| 229 | @ </ul> |
| 230 | style_footer(); |
| 231 | } |
| 232 |
| --- src/cookies.c | |
| +++ src/cookies.c | |
| @@ -225,7 +225,7 @@ | |
| 225 | @ <li>Raw cookie value: "%h(PD("fossil_display_settings",""))" |
| 226 | for(i=0; i<cookies.nParam; i++){ |
| 227 | @ <li>%h(cookies.aParam[i].zPName): "%h(cookies.aParam[i].zPValue)" |
| 228 | } |
| 229 | @ </ul> |
| 230 | style_finish_page("cookies"); |
| 231 | } |
| 232 |
M
src/db.c
+5
-4
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -3499,19 +3499,20 @@ | ||
| 3499 | 3499 | |
| 3500 | 3500 | /* If REPOSITORY looks like a URI, then try to clone it first */ |
| 3501 | 3501 | if( isUri ){ |
| 3502 | 3502 | char *zNewBase; /* Base name of the cloned repository file */ |
| 3503 | 3503 | const char *zUri; /* URI to clone */ |
| 3504 | - int i; /* Loop counter */ | |
| 3505 | 3504 | int rc; /* Result code from fossil_system() */ |
| 3506 | 3505 | Blob cmd; /* Clone command to be run */ |
| 3507 | 3506 | char *zCmd; /* String version of the clone command */ |
| 3508 | 3507 | |
| 3509 | 3508 | zUri = zRepo; |
| 3510 | - zNewBase = fossil_strdup(file_tail(zUri)); | |
| 3511 | - for(i=(int)strlen(zNewBase)-1; i>1 && zNewBase[i]!='.'; i--){} | |
| 3512 | - if( zNewBase[i]=='.' ) zNewBase[i] = 0; | |
| 3509 | + zNewBase = url_to_repo_basename(zUri); | |
| 3510 | + if( zNewBase==0 ){ | |
| 3511 | + fossil_fatal("unable to deduce a repository name from the url \"%s\"", | |
| 3512 | + zUri); | |
| 3513 | + } | |
| 3513 | 3514 | if( zRepoDir==0 ) zRepoDir = zPwd; |
| 3514 | 3515 | zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); |
| 3515 | 3516 | fossil_free(zNewBase); |
| 3516 | 3517 | blob_init(&cmd, 0, 0); |
| 3517 | 3518 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 3518 | 3519 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3499,19 +3499,20 @@ | |
| 3499 | |
| 3500 | /* If REPOSITORY looks like a URI, then try to clone it first */ |
| 3501 | if( isUri ){ |
| 3502 | char *zNewBase; /* Base name of the cloned repository file */ |
| 3503 | const char *zUri; /* URI to clone */ |
| 3504 | int i; /* Loop counter */ |
| 3505 | int rc; /* Result code from fossil_system() */ |
| 3506 | Blob cmd; /* Clone command to be run */ |
| 3507 | char *zCmd; /* String version of the clone command */ |
| 3508 | |
| 3509 | zUri = zRepo; |
| 3510 | zNewBase = fossil_strdup(file_tail(zUri)); |
| 3511 | for(i=(int)strlen(zNewBase)-1; i>1 && zNewBase[i]!='.'; i--){} |
| 3512 | if( zNewBase[i]=='.' ) zNewBase[i] = 0; |
| 3513 | if( zRepoDir==0 ) zRepoDir = zPwd; |
| 3514 | zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); |
| 3515 | fossil_free(zNewBase); |
| 3516 | blob_init(&cmd, 0, 0); |
| 3517 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 3518 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3499,19 +3499,20 @@ | |
| 3499 | |
| 3500 | /* If REPOSITORY looks like a URI, then try to clone it first */ |
| 3501 | if( isUri ){ |
| 3502 | char *zNewBase; /* Base name of the cloned repository file */ |
| 3503 | const char *zUri; /* URI to clone */ |
| 3504 | int rc; /* Result code from fossil_system() */ |
| 3505 | Blob cmd; /* Clone command to be run */ |
| 3506 | char *zCmd; /* String version of the clone command */ |
| 3507 | |
| 3508 | zUri = zRepo; |
| 3509 | zNewBase = url_to_repo_basename(zUri); |
| 3510 | if( zNewBase==0 ){ |
| 3511 | fossil_fatal("unable to deduce a repository name from the url \"%s\"", |
| 3512 | zUri); |
| 3513 | } |
| 3514 | if( zRepoDir==0 ) zRepoDir = zPwd; |
| 3515 | zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); |
| 3516 | fossil_free(zNewBase); |
| 3517 | blob_init(&cmd, 0, 0); |
| 3518 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 3519 |
+2
-6
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -752,23 +752,19 @@ | ||
| 752 | 752 | white-space: pre-wrap; |
| 753 | 753 | } |
| 754 | 754 | div.markdown code { |
| 755 | 755 | white-space: pre-wrap; |
| 756 | 756 | } |
| 757 | -div.forumHier, div.forumTime { | |
| 757 | +div.forumTime { | |
| 758 | 758 | border: 1px solid black; |
| 759 | 759 | padding-left: 1ex; |
| 760 | 760 | padding-right: 1ex; |
| 761 | 761 | margin-top: 1ex; |
| 762 | -} | |
| 763 | -div.forumHier, div.forumTime, div.forumHierRoot { | |
| 764 | 762 | display: flex; |
| 765 | 763 | flex-direction: column; |
| 766 | 764 | } |
| 767 | -div.forumHier > div > form, | |
| 768 | -div.forumTime > div > form, | |
| 769 | -div.forumHierRoot > div > form { | |
| 765 | +.forum div > form { | |
| 770 | 766 | margin: 0.5em 0; |
| 771 | 767 | } |
| 772 | 768 | .forum-post-collapser { |
| 773 | 769 | /* Common style for the bottom-of-post and right-of-post |
| 774 | 770 | expand/collapse widgets. */ |
| 775 | 771 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -752,23 +752,19 @@ | |
| 752 | white-space: pre-wrap; |
| 753 | } |
| 754 | div.markdown code { |
| 755 | white-space: pre-wrap; |
| 756 | } |
| 757 | div.forumHier, div.forumTime { |
| 758 | border: 1px solid black; |
| 759 | padding-left: 1ex; |
| 760 | padding-right: 1ex; |
| 761 | margin-top: 1ex; |
| 762 | } |
| 763 | div.forumHier, div.forumTime, div.forumHierRoot { |
| 764 | display: flex; |
| 765 | flex-direction: column; |
| 766 | } |
| 767 | div.forumHier > div > form, |
| 768 | div.forumTime > div > form, |
| 769 | div.forumHierRoot > div > form { |
| 770 | margin: 0.5em 0; |
| 771 | } |
| 772 | .forum-post-collapser { |
| 773 | /* Common style for the bottom-of-post and right-of-post |
| 774 | expand/collapse widgets. */ |
| 775 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -752,23 +752,19 @@ | |
| 752 | white-space: pre-wrap; |
| 753 | } |
| 754 | div.markdown code { |
| 755 | white-space: pre-wrap; |
| 756 | } |
| 757 | div.forumTime { |
| 758 | border: 1px solid black; |
| 759 | padding-left: 1ex; |
| 760 | padding-right: 1ex; |
| 761 | margin-top: 1ex; |
| 762 | display: flex; |
| 763 | flex-direction: column; |
| 764 | } |
| 765 | .forum div > form { |
| 766 | margin: 0.5em 0; |
| 767 | } |
| 768 | .forum-post-collapser { |
| 769 | /* Common style for the bottom-of-post and right-of-post |
| 770 | expand/collapse widgets. */ |
| 771 |
+1
-1
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -613,11 +613,11 @@ | ||
| 613 | 613 | if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR; |
| 614 | 614 | if( fUBg ) tmFlags |= TIMELINE_UCOLOR; |
| 615 | 615 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); |
| 616 | 616 | db_finalize(&q); |
| 617 | 617 | @ <br /> |
| 618 | - style_footer(); | |
| 618 | + style_finish_page("leaves"); | |
| 619 | 619 | } |
| 620 | 620 | |
| 621 | 621 | #if INTERFACE |
| 622 | 622 | /* Flag parameters to compute_uses_file() */ |
| 623 | 623 | #define USESFILE_DELETE 0x01 /* Include the check-ins where file deleted */ |
| 624 | 624 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -613,11 +613,11 @@ | |
| 613 | if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR; |
| 614 | if( fUBg ) tmFlags |= TIMELINE_UCOLOR; |
| 615 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); |
| 616 | db_finalize(&q); |
| 617 | @ <br /> |
| 618 | style_footer(); |
| 619 | } |
| 620 | |
| 621 | #if INTERFACE |
| 622 | /* Flag parameters to compute_uses_file() */ |
| 623 | #define USESFILE_DELETE 0x01 /* Include the check-ins where file deleted */ |
| 624 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -613,11 +613,11 @@ | |
| 613 | if( fBrBg ) tmFlags |= TIMELINE_BRCOLOR; |
| 614 | if( fUBg ) tmFlags |= TIMELINE_UCOLOR; |
| 615 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); |
| 616 | db_finalize(&q); |
| 617 | @ <br /> |
| 618 | style_finish_page("leaves"); |
| 619 | } |
| 620 | |
| 621 | #if INTERFACE |
| 622 | /* Flag parameters to compute_uses_file() */ |
| 623 | #define USESFILE_DELETE 0x01 /* Include the check-ins where file deleted */ |
| 624 |
+1
-1
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -2556,11 +2556,11 @@ | ||
| 2556 | 2556 | } |
| 2557 | 2557 | @ %s(zPrefix) %h(z) |
| 2558 | 2558 | |
| 2559 | 2559 | } |
| 2560 | 2560 | @ </pre> |
| 2561 | - style_footer(); | |
| 2561 | + style_finish_page("annotate"); | |
| 2562 | 2562 | } |
| 2563 | 2563 | |
| 2564 | 2564 | /* |
| 2565 | 2565 | ** COMMAND: annotate |
| 2566 | 2566 | ** COMMAND: blame |
| 2567 | 2567 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2556,11 +2556,11 @@ | |
| 2556 | } |
| 2557 | @ %s(zPrefix) %h(z) |
| 2558 | |
| 2559 | } |
| 2560 | @ </pre> |
| 2561 | style_footer(); |
| 2562 | } |
| 2563 | |
| 2564 | /* |
| 2565 | ** COMMAND: annotate |
| 2566 | ** COMMAND: blame |
| 2567 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2556,11 +2556,11 @@ | |
| 2556 | } |
| 2557 | @ %s(zPrefix) %h(z) |
| 2558 | |
| 2559 | } |
| 2560 | @ </pre> |
| 2561 | style_finish_page("annotate"); |
| 2562 | } |
| 2563 | |
| 2564 | /* |
| 2565 | ** COMMAND: annotate |
| 2566 | ** COMMAND: blame |
| 2567 |
+2
-2
| --- src/dispatch.c | ||
| +++ src/dispatch.c | ||
| @@ -850,11 +850,11 @@ | ||
| 850 | 850 | } |
| 851 | 851 | } |
| 852 | 852 | @ </ul></div> |
| 853 | 853 | |
| 854 | 854 | } |
| 855 | - style_footer(); | |
| 855 | + style_finish_page("help"); | |
| 856 | 856 | } |
| 857 | 857 | |
| 858 | 858 | /* |
| 859 | 859 | ** WEBPAGE: test-all-help |
| 860 | 860 | ** |
| @@ -901,11 +901,11 @@ | ||
| 901 | 901 | help_to_html(aCommand[i].zHelp, cgi_output_blob()); |
| 902 | 902 | @ </dd> |
| 903 | 903 | } |
| 904 | 904 | @ </dl> |
| 905 | 905 | blob_reset(&buf); |
| 906 | - style_footer(); | |
| 906 | + style_finish_page("help"); | |
| 907 | 907 | } |
| 908 | 908 | |
| 909 | 909 | static void multi_column_list(const char **azWord, int nWord){ |
| 910 | 910 | int i, j, len; |
| 911 | 911 | int mxLen = 0; |
| 912 | 912 |
| --- src/dispatch.c | |
| +++ src/dispatch.c | |
| @@ -850,11 +850,11 @@ | |
| 850 | } |
| 851 | } |
| 852 | @ </ul></div> |
| 853 | |
| 854 | } |
| 855 | style_footer(); |
| 856 | } |
| 857 | |
| 858 | /* |
| 859 | ** WEBPAGE: test-all-help |
| 860 | ** |
| @@ -901,11 +901,11 @@ | |
| 901 | help_to_html(aCommand[i].zHelp, cgi_output_blob()); |
| 902 | @ </dd> |
| 903 | } |
| 904 | @ </dl> |
| 905 | blob_reset(&buf); |
| 906 | style_footer(); |
| 907 | } |
| 908 | |
| 909 | static void multi_column_list(const char **azWord, int nWord){ |
| 910 | int i, j, len; |
| 911 | int mxLen = 0; |
| 912 |
| --- src/dispatch.c | |
| +++ src/dispatch.c | |
| @@ -850,11 +850,11 @@ | |
| 850 | } |
| 851 | } |
| 852 | @ </ul></div> |
| 853 | |
| 854 | } |
| 855 | style_finish_page("help"); |
| 856 | } |
| 857 | |
| 858 | /* |
| 859 | ** WEBPAGE: test-all-help |
| 860 | ** |
| @@ -901,11 +901,11 @@ | |
| 901 | help_to_html(aCommand[i].zHelp, cgi_output_blob()); |
| 902 | @ </dd> |
| 903 | } |
| 904 | @ </dl> |
| 905 | blob_reset(&buf); |
| 906 | style_finish_page("help"); |
| 907 | } |
| 908 | |
| 909 | static void multi_column_list(const char **azWord, int nWord){ |
| 910 | int i, j, len; |
| 911 | int mxLen = 0; |
| 912 |
+9
-9
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -555,11 +555,11 @@ | ||
| 555 | 555 | } |
| 556 | 556 | @ <tr><td>%s(zFlag)%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr> |
| 557 | 557 | } |
| 558 | 558 | @ </tbody></table> |
| 559 | 559 | style_table_sorter(); |
| 560 | - style_footer(); | |
| 560 | + style_finish_page("mimetypes"); | |
| 561 | 561 | } |
| 562 | 562 | |
| 563 | 563 | /* |
| 564 | 564 | ** Check to see if the file in the pContent blob is "embedded HTML". Return |
| 565 | 565 | ** true if it is, and fill pTitle with the document title. |
| @@ -770,11 +770,11 @@ | ||
| 770 | 770 | }else{ |
| 771 | 771 | style_header("%s", zDefaultTitle); |
| 772 | 772 | wiki_convert(pBody, 0, WIKI_BUTTONS); |
| 773 | 773 | } |
| 774 | 774 | document_emit_js(); |
| 775 | - style_footer(); | |
| 775 | + style_finish_page("doc"); | |
| 776 | 776 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 777 | 777 | Blob tail = BLOB_INITIALIZER; |
| 778 | 778 | markdown_to_html(pBody, &title, &tail); |
| 779 | 779 | if( blob_size(&title)>0 ){ |
| 780 | 780 | style_header("%s", blob_str(&title)); |
| @@ -781,30 +781,30 @@ | ||
| 781 | 781 | }else{ |
| 782 | 782 | style_header("%s", zDefaultTitle); |
| 783 | 783 | } |
| 784 | 784 | convert_href_and_output(&tail); |
| 785 | 785 | document_emit_js(); |
| 786 | - style_footer(); | |
| 786 | + style_finish_page("doc"); | |
| 787 | 787 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 788 | 788 | style_header("%s", zDefaultTitle); |
| 789 | 789 | @ <blockquote><pre> |
| 790 | 790 | @ %h(blob_str(pBody)) |
| 791 | 791 | @ </pre></blockquote> |
| 792 | 792 | document_emit_js(); |
| 793 | - style_footer(); | |
| 793 | + style_finish_page("doc"); | |
| 794 | 794 | }else if( fossil_strcmp(zMime, "text/html")==0 |
| 795 | 795 | && doc_is_embedded_html(pBody, &title) ){ |
| 796 | 796 | if( blob_size(&title)==0 ) blob_append(&title,zFilename,-1); |
| 797 | 797 | style_header("%s", blob_str(&title)); |
| 798 | 798 | convert_href_and_output(pBody); |
| 799 | 799 | document_emit_js(); |
| 800 | - style_footer(); | |
| 800 | + style_finish_page("doc"); | |
| 801 | 801 | }else if( fossil_strcmp(zMime, "text/x-pikchr")==0 ){ |
| 802 | 802 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 803 | 803 | style_header("%s", zDefaultTitle); |
| 804 | 804 | wiki_render_by_mimetype(pBody, zMime); |
| 805 | - style_footer(); | |
| 805 | + style_finish_page("doc"); | |
| 806 | 806 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 807 | 807 | }else if( Th_AreDocsEnabled() && |
| 808 | 808 | fossil_strcmp(zMime, "application/x-th1")==0 ){ |
| 809 | 809 | int raw = P("raw")!=0; |
| 810 | 810 | if( !raw ){ |
| @@ -821,11 +821,11 @@ | ||
| 821 | 821 | }else{ |
| 822 | 822 | Th_Render(blob_str(pBody)); |
| 823 | 823 | } |
| 824 | 824 | if( !raw ){ |
| 825 | 825 | document_emit_js(); |
| 826 | - style_footer(); | |
| 826 | + style_finish_page("doc"); | |
| 827 | 827 | } |
| 828 | 828 | #endif |
| 829 | 829 | }else{ |
| 830 | 830 | fossil_free(style_csp(1)); |
| 831 | 831 | cgi_set_content_type(zMime); |
| @@ -1029,11 +1029,11 @@ | ||
| 1029 | 1029 | style_header("Not Found"); |
| 1030 | 1030 | @ <p>Document %h(zOrigName) not found |
| 1031 | 1031 | if( fossil_strcmp(zCheckin,"ckout")!=0 ){ |
| 1032 | 1032 | @ in %z(href("%R/tree?ci=%T",zCheckin))%h(zCheckin)</a> |
| 1033 | 1033 | } |
| 1034 | - style_footer(); | |
| 1034 | + style_finish_page("doc"); | |
| 1035 | 1035 | return; |
| 1036 | 1036 | } |
| 1037 | 1037 | |
| 1038 | 1038 | /* |
| 1039 | 1039 | ** The default logo. |
| @@ -1202,7 +1202,7 @@ | ||
| 1202 | 1202 | */ |
| 1203 | 1203 | void doc_search_page(void){ |
| 1204 | 1204 | login_check_credentials(); |
| 1205 | 1205 | style_header("Document Search"); |
| 1206 | 1206 | search_screen(SRCH_DOC, 0); |
| 1207 | - style_footer(); | |
| 1207 | + style_finish_page("docsrch"); | |
| 1208 | 1208 | } |
| 1209 | 1209 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -555,11 +555,11 @@ | |
| 555 | } |
| 556 | @ <tr><td>%s(zFlag)%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr> |
| 557 | } |
| 558 | @ </tbody></table> |
| 559 | style_table_sorter(); |
| 560 | style_footer(); |
| 561 | } |
| 562 | |
| 563 | /* |
| 564 | ** Check to see if the file in the pContent blob is "embedded HTML". Return |
| 565 | ** true if it is, and fill pTitle with the document title. |
| @@ -770,11 +770,11 @@ | |
| 770 | }else{ |
| 771 | style_header("%s", zDefaultTitle); |
| 772 | wiki_convert(pBody, 0, WIKI_BUTTONS); |
| 773 | } |
| 774 | document_emit_js(); |
| 775 | style_footer(); |
| 776 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 777 | Blob tail = BLOB_INITIALIZER; |
| 778 | markdown_to_html(pBody, &title, &tail); |
| 779 | if( blob_size(&title)>0 ){ |
| 780 | style_header("%s", blob_str(&title)); |
| @@ -781,30 +781,30 @@ | |
| 781 | }else{ |
| 782 | style_header("%s", zDefaultTitle); |
| 783 | } |
| 784 | convert_href_and_output(&tail); |
| 785 | document_emit_js(); |
| 786 | style_footer(); |
| 787 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 788 | style_header("%s", zDefaultTitle); |
| 789 | @ <blockquote><pre> |
| 790 | @ %h(blob_str(pBody)) |
| 791 | @ </pre></blockquote> |
| 792 | document_emit_js(); |
| 793 | style_footer(); |
| 794 | }else if( fossil_strcmp(zMime, "text/html")==0 |
| 795 | && doc_is_embedded_html(pBody, &title) ){ |
| 796 | if( blob_size(&title)==0 ) blob_append(&title,zFilename,-1); |
| 797 | style_header("%s", blob_str(&title)); |
| 798 | convert_href_and_output(pBody); |
| 799 | document_emit_js(); |
| 800 | style_footer(); |
| 801 | }else if( fossil_strcmp(zMime, "text/x-pikchr")==0 ){ |
| 802 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 803 | style_header("%s", zDefaultTitle); |
| 804 | wiki_render_by_mimetype(pBody, zMime); |
| 805 | style_footer(); |
| 806 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 807 | }else if( Th_AreDocsEnabled() && |
| 808 | fossil_strcmp(zMime, "application/x-th1")==0 ){ |
| 809 | int raw = P("raw")!=0; |
| 810 | if( !raw ){ |
| @@ -821,11 +821,11 @@ | |
| 821 | }else{ |
| 822 | Th_Render(blob_str(pBody)); |
| 823 | } |
| 824 | if( !raw ){ |
| 825 | document_emit_js(); |
| 826 | style_footer(); |
| 827 | } |
| 828 | #endif |
| 829 | }else{ |
| 830 | fossil_free(style_csp(1)); |
| 831 | cgi_set_content_type(zMime); |
| @@ -1029,11 +1029,11 @@ | |
| 1029 | style_header("Not Found"); |
| 1030 | @ <p>Document %h(zOrigName) not found |
| 1031 | if( fossil_strcmp(zCheckin,"ckout")!=0 ){ |
| 1032 | @ in %z(href("%R/tree?ci=%T",zCheckin))%h(zCheckin)</a> |
| 1033 | } |
| 1034 | style_footer(); |
| 1035 | return; |
| 1036 | } |
| 1037 | |
| 1038 | /* |
| 1039 | ** The default logo. |
| @@ -1202,7 +1202,7 @@ | |
| 1202 | */ |
| 1203 | void doc_search_page(void){ |
| 1204 | login_check_credentials(); |
| 1205 | style_header("Document Search"); |
| 1206 | search_screen(SRCH_DOC, 0); |
| 1207 | style_footer(); |
| 1208 | } |
| 1209 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -555,11 +555,11 @@ | |
| 555 | } |
| 556 | @ <tr><td>%s(zFlag)%h(aMime[i].zSuffix)<td>%h(aMime[i].zMimetype)</tr> |
| 557 | } |
| 558 | @ </tbody></table> |
| 559 | style_table_sorter(); |
| 560 | style_finish_page("mimetypes"); |
| 561 | } |
| 562 | |
| 563 | /* |
| 564 | ** Check to see if the file in the pContent blob is "embedded HTML". Return |
| 565 | ** true if it is, and fill pTitle with the document title. |
| @@ -770,11 +770,11 @@ | |
| 770 | }else{ |
| 771 | style_header("%s", zDefaultTitle); |
| 772 | wiki_convert(pBody, 0, WIKI_BUTTONS); |
| 773 | } |
| 774 | document_emit_js(); |
| 775 | style_finish_page("doc"); |
| 776 | }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){ |
| 777 | Blob tail = BLOB_INITIALIZER; |
| 778 | markdown_to_html(pBody, &title, &tail); |
| 779 | if( blob_size(&title)>0 ){ |
| 780 | style_header("%s", blob_str(&title)); |
| @@ -781,30 +781,30 @@ | |
| 781 | }else{ |
| 782 | style_header("%s", zDefaultTitle); |
| 783 | } |
| 784 | convert_href_and_output(&tail); |
| 785 | document_emit_js(); |
| 786 | style_finish_page("doc"); |
| 787 | }else if( fossil_strcmp(zMime, "text/plain")==0 ){ |
| 788 | style_header("%s", zDefaultTitle); |
| 789 | @ <blockquote><pre> |
| 790 | @ %h(blob_str(pBody)) |
| 791 | @ </pre></blockquote> |
| 792 | document_emit_js(); |
| 793 | style_finish_page("doc"); |
| 794 | }else if( fossil_strcmp(zMime, "text/html")==0 |
| 795 | && doc_is_embedded_html(pBody, &title) ){ |
| 796 | if( blob_size(&title)==0 ) blob_append(&title,zFilename,-1); |
| 797 | style_header("%s", blob_str(&title)); |
| 798 | convert_href_and_output(pBody); |
| 799 | document_emit_js(); |
| 800 | style_finish_page("doc"); |
| 801 | }else if( fossil_strcmp(zMime, "text/x-pikchr")==0 ){ |
| 802 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 803 | style_header("%s", zDefaultTitle); |
| 804 | wiki_render_by_mimetype(pBody, zMime); |
| 805 | style_finish_page("doc"); |
| 806 | #ifdef FOSSIL_ENABLE_TH1_DOCS |
| 807 | }else if( Th_AreDocsEnabled() && |
| 808 | fossil_strcmp(zMime, "application/x-th1")==0 ){ |
| 809 | int raw = P("raw")!=0; |
| 810 | if( !raw ){ |
| @@ -821,11 +821,11 @@ | |
| 821 | }else{ |
| 822 | Th_Render(blob_str(pBody)); |
| 823 | } |
| 824 | if( !raw ){ |
| 825 | document_emit_js(); |
| 826 | style_finish_page("doc"); |
| 827 | } |
| 828 | #endif |
| 829 | }else{ |
| 830 | fossil_free(style_csp(1)); |
| 831 | cgi_set_content_type(zMime); |
| @@ -1029,11 +1029,11 @@ | |
| 1029 | style_header("Not Found"); |
| 1030 | @ <p>Document %h(zOrigName) not found |
| 1031 | if( fossil_strcmp(zCheckin,"ckout")!=0 ){ |
| 1032 | @ in %z(href("%R/tree?ci=%T",zCheckin))%h(zCheckin)</a> |
| 1033 | } |
| 1034 | style_finish_page("doc"); |
| 1035 | return; |
| 1036 | } |
| 1037 | |
| 1038 | /* |
| 1039 | ** The default logo. |
| @@ -1202,7 +1202,7 @@ | |
| 1202 | */ |
| 1203 | void doc_search_page(void){ |
| 1204 | login_check_credentials(); |
| 1205 | style_header("Document Search"); |
| 1206 | search_screen(SRCH_DOC, 0); |
| 1207 | style_finish_page("docsrch"); |
| 1208 | } |
| 1209 |
+4
-4
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -113,11 +113,11 @@ | ||
| 113 | 113 | } |
| 114 | 114 | db_finalize(&q1); |
| 115 | 115 | if( rid==0 || (specRid!=0 && specRid!=rid) ){ |
| 116 | 116 | style_header("No Such Tech-Note"); |
| 117 | 117 | @ Cannot locate a technical note called <b>%h(zId)</b>. |
| 118 | - style_footer(); | |
| 118 | + style_finish_page("event"); | |
| 119 | 119 | return; |
| 120 | 120 | } |
| 121 | 121 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 122 | 122 | zVerbose = P("v"); |
| 123 | 123 | if( !zVerbose ){ |
| @@ -229,11 +229,11 @@ | ||
| 229 | 229 | " FROM tag" |
| 230 | 230 | " WHERE tagname GLOB 'event-%q*'", |
| 231 | 231 | zId); |
| 232 | 232 | attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>"); |
| 233 | 233 | document_emit_js(); |
| 234 | - style_footer(); | |
| 234 | + style_finish_page("event"); | |
| 235 | 235 | manifest_destroy(pTNote); |
| 236 | 236 | } |
| 237 | 237 | |
| 238 | 238 | /* |
| 239 | 239 | ** Add or update a new tech note to the repository. rid is id of |
| @@ -473,11 +473,11 @@ | ||
| 473 | 473 | zMimetype, zComment, zTags, |
| 474 | 474 | zClrFlag[0] ? zClr : 0) ){ |
| 475 | 475 | style_header("Error"); |
| 476 | 476 | @ Internal error: Fossil tried to make an invalid artifact for |
| 477 | 477 | @ the edited technote. |
| 478 | - style_footer(); | |
| 478 | + style_finish_page("event"); | |
| 479 | 479 | return; |
| 480 | 480 | } |
| 481 | 481 | cgi_redirectf("%R/technote?name=%T", zId); |
| 482 | 482 | } |
| 483 | 483 | if( P("cancel")!=0 ){ |
| @@ -567,11 +567,11 @@ | ||
| 567 | 567 | if( P("preview") ){ |
| 568 | 568 | @ <input type="submit" name="submit" value="Submit" /> |
| 569 | 569 | } |
| 570 | 570 | @ </td></tr></table> |
| 571 | 571 | @ </div></form> |
| 572 | - style_footer(); | |
| 572 | + style_finish_page("event"); | |
| 573 | 573 | } |
| 574 | 574 | |
| 575 | 575 | /* |
| 576 | 576 | ** Add a new tech note to the repository. The timestamp is |
| 577 | 577 | ** given by the zETime parameter. rid must be zero to create |
| 578 | 578 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -113,11 +113,11 @@ | |
| 113 | } |
| 114 | db_finalize(&q1); |
| 115 | if( rid==0 || (specRid!=0 && specRid!=rid) ){ |
| 116 | style_header("No Such Tech-Note"); |
| 117 | @ Cannot locate a technical note called <b>%h(zId)</b>. |
| 118 | style_footer(); |
| 119 | return; |
| 120 | } |
| 121 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 122 | zVerbose = P("v"); |
| 123 | if( !zVerbose ){ |
| @@ -229,11 +229,11 @@ | |
| 229 | " FROM tag" |
| 230 | " WHERE tagname GLOB 'event-%q*'", |
| 231 | zId); |
| 232 | attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>"); |
| 233 | document_emit_js(); |
| 234 | style_footer(); |
| 235 | manifest_destroy(pTNote); |
| 236 | } |
| 237 | |
| 238 | /* |
| 239 | ** Add or update a new tech note to the repository. rid is id of |
| @@ -473,11 +473,11 @@ | |
| 473 | zMimetype, zComment, zTags, |
| 474 | zClrFlag[0] ? zClr : 0) ){ |
| 475 | style_header("Error"); |
| 476 | @ Internal error: Fossil tried to make an invalid artifact for |
| 477 | @ the edited technote. |
| 478 | style_footer(); |
| 479 | return; |
| 480 | } |
| 481 | cgi_redirectf("%R/technote?name=%T", zId); |
| 482 | } |
| 483 | if( P("cancel")!=0 ){ |
| @@ -567,11 +567,11 @@ | |
| 567 | if( P("preview") ){ |
| 568 | @ <input type="submit" name="submit" value="Submit" /> |
| 569 | } |
| 570 | @ </td></tr></table> |
| 571 | @ </div></form> |
| 572 | style_footer(); |
| 573 | } |
| 574 | |
| 575 | /* |
| 576 | ** Add a new tech note to the repository. The timestamp is |
| 577 | ** given by the zETime parameter. rid must be zero to create |
| 578 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -113,11 +113,11 @@ | |
| 113 | } |
| 114 | db_finalize(&q1); |
| 115 | if( rid==0 || (specRid!=0 && specRid!=rid) ){ |
| 116 | style_header("No Such Tech-Note"); |
| 117 | @ Cannot locate a technical note called <b>%h(zId)</b>. |
| 118 | style_finish_page("event"); |
| 119 | return; |
| 120 | } |
| 121 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 122 | zVerbose = P("v"); |
| 123 | if( !zVerbose ){ |
| @@ -229,11 +229,11 @@ | |
| 229 | " FROM tag" |
| 230 | " WHERE tagname GLOB 'event-%q*'", |
| 231 | zId); |
| 232 | attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>"); |
| 233 | document_emit_js(); |
| 234 | style_finish_page("event"); |
| 235 | manifest_destroy(pTNote); |
| 236 | } |
| 237 | |
| 238 | /* |
| 239 | ** Add or update a new tech note to the repository. rid is id of |
| @@ -473,11 +473,11 @@ | |
| 473 | zMimetype, zComment, zTags, |
| 474 | zClrFlag[0] ? zClr : 0) ){ |
| 475 | style_header("Error"); |
| 476 | @ Internal error: Fossil tried to make an invalid artifact for |
| 477 | @ the edited technote. |
| 478 | style_finish_page("event"); |
| 479 | return; |
| 480 | } |
| 481 | cgi_redirectf("%R/technote?name=%T", zId); |
| 482 | } |
| 483 | if( P("cancel")!=0 ){ |
| @@ -567,11 +567,11 @@ | |
| 567 | if( P("preview") ){ |
| 568 | @ <input type="submit" name="submit" value="Submit" /> |
| 569 | } |
| 570 | @ </td></tr></table> |
| 571 | @ </div></form> |
| 572 | style_finish_page("event"); |
| 573 | } |
| 574 | |
| 575 | /* |
| 576 | ** Add a new tech note to the repository. The timestamp is |
| 577 | ** given by the zETime parameter. rid must be zero to create |
| 578 |
+1
-1
| --- src/extcgi.c | ||
| +++ src/extcgi.c | ||
| @@ -416,7 +416,7 @@ | ||
| 416 | 416 | @ </tr> |
| 417 | 417 | } |
| 418 | 418 | db_finalize(&q); |
| 419 | 419 | @ </tbody> |
| 420 | 420 | @ </table> |
| 421 | - style_footer(); | |
| 421 | + style_finish_page("extcgi"); | |
| 422 | 422 | } |
| 423 | 423 |
| --- src/extcgi.c | |
| +++ src/extcgi.c | |
| @@ -416,7 +416,7 @@ | |
| 416 | @ </tr> |
| 417 | } |
| 418 | db_finalize(&q); |
| 419 | @ </tbody> |
| 420 | @ </table> |
| 421 | style_footer(); |
| 422 | } |
| 423 |
| --- src/extcgi.c | |
| +++ src/extcgi.c | |
| @@ -416,7 +416,7 @@ | |
| 416 | @ </tr> |
| 417 | } |
| 418 | db_finalize(&q); |
| 419 | @ </tbody> |
| 420 | @ </table> |
| 421 | style_finish_page("extcgi"); |
| 422 | } |
| 423 |
+2
-2
| --- src/fileedit.c | ||
| +++ src/fileedit.c | ||
| @@ -1606,11 +1606,11 @@ | ||
| 1606 | 1606 | "values matching files which may be edited online." |
| 1607 | 1607 | "</p>\n"); |
| 1608 | 1608 | }else{ |
| 1609 | 1609 | CX("<p>Online editing is disabled for this repository.</p>\n"); |
| 1610 | 1610 | } |
| 1611 | - style_footer(); | |
| 1611 | + style_finish_page("fileedit"); | |
| 1612 | 1612 | return; |
| 1613 | 1613 | } |
| 1614 | 1614 | |
| 1615 | 1615 | /* Dispatch AJAX methods based tail of the request URI. |
| 1616 | 1616 | ** The AJAX parts do their own permissions/CSRF check and |
| @@ -2061,7 +2061,7 @@ | ||
| 2061 | 2061 | style_script_end(); |
| 2062 | 2062 | } |
| 2063 | 2063 | blob_reset(&err); |
| 2064 | 2064 | CheckinMiniInfo_cleanup(&cimi); |
| 2065 | 2065 | db_end_transaction(0); |
| 2066 | - style_footer(); | |
| 2066 | + style_finish_page("fileedit"); | |
| 2067 | 2067 | } |
| 2068 | 2068 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1606,11 +1606,11 @@ | |
| 1606 | "values matching files which may be edited online." |
| 1607 | "</p>\n"); |
| 1608 | }else{ |
| 1609 | CX("<p>Online editing is disabled for this repository.</p>\n"); |
| 1610 | } |
| 1611 | style_footer(); |
| 1612 | return; |
| 1613 | } |
| 1614 | |
| 1615 | /* Dispatch AJAX methods based tail of the request URI. |
| 1616 | ** The AJAX parts do their own permissions/CSRF check and |
| @@ -2061,7 +2061,7 @@ | |
| 2061 | style_script_end(); |
| 2062 | } |
| 2063 | blob_reset(&err); |
| 2064 | CheckinMiniInfo_cleanup(&cimi); |
| 2065 | db_end_transaction(0); |
| 2066 | style_footer(); |
| 2067 | } |
| 2068 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1606,11 +1606,11 @@ | |
| 1606 | "values matching files which may be edited online." |
| 1607 | "</p>\n"); |
| 1608 | }else{ |
| 1609 | CX("<p>Online editing is disabled for this repository.</p>\n"); |
| 1610 | } |
| 1611 | style_finish_page("fileedit"); |
| 1612 | return; |
| 1613 | } |
| 1614 | |
| 1615 | /* Dispatch AJAX methods based tail of the request URI. |
| 1616 | ** The AJAX parts do their own permissions/CSRF check and |
| @@ -2061,7 +2061,7 @@ | |
| 2061 | style_script_end(); |
| 2062 | } |
| 2063 | blob_reset(&err); |
| 2064 | CheckinMiniInfo_cleanup(&cimi); |
| 2065 | db_end_transaction(0); |
| 2066 | style_finish_page("fileedit"); |
| 2067 | } |
| 2068 |
+3
-3
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -367,11 +367,11 @@ | ||
| 367 | 367 | ridFrom = name_to_rid_www("from"); |
| 368 | 368 | zPrevDate[0] = 0; |
| 369 | 369 | cookie_render(); |
| 370 | 370 | if( fnid==0 ){ |
| 371 | 371 | @ No such file: %h(zFilename) |
| 372 | - style_footer(); | |
| 372 | + style_finish_page("finfo"); | |
| 373 | 373 | return; |
| 374 | 374 | } |
| 375 | 375 | if( g.perm.Admin ){ |
| 376 | 376 | style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename); |
| 377 | 377 | } |
| @@ -754,11 +754,11 @@ | ||
| 754 | 754 | @ <td></td><td></td><td></td></tr> |
| 755 | 755 | } |
| 756 | 756 | } |
| 757 | 757 | @ </table> |
| 758 | 758 | timeline_output_graph_javascript(pGraph, TIMELINE_FILEDIFF, iTableId); |
| 759 | - style_footer(); | |
| 759 | + style_finish_page("finfo"); | |
| 760 | 760 | } |
| 761 | 761 | |
| 762 | 762 | /* |
| 763 | 763 | ** WEBPAGE: mlink |
| 764 | 764 | ** URL: /mlink?name=FILENAME |
| @@ -934,7 +934,7 @@ | ||
| 934 | 934 | db_finalize(&q); |
| 935 | 935 | @ </tbody> |
| 936 | 936 | @ </table> |
| 937 | 937 | @ </div> |
| 938 | 938 | } |
| 939 | - style_footer(); | |
| 939 | + style_finish_page("finfo"); | |
| 940 | 940 | } |
| 941 | 941 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -367,11 +367,11 @@ | |
| 367 | ridFrom = name_to_rid_www("from"); |
| 368 | zPrevDate[0] = 0; |
| 369 | cookie_render(); |
| 370 | if( fnid==0 ){ |
| 371 | @ No such file: %h(zFilename) |
| 372 | style_footer(); |
| 373 | return; |
| 374 | } |
| 375 | if( g.perm.Admin ){ |
| 376 | style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename); |
| 377 | } |
| @@ -754,11 +754,11 @@ | |
| 754 | @ <td></td><td></td><td></td></tr> |
| 755 | } |
| 756 | } |
| 757 | @ </table> |
| 758 | timeline_output_graph_javascript(pGraph, TIMELINE_FILEDIFF, iTableId); |
| 759 | style_footer(); |
| 760 | } |
| 761 | |
| 762 | /* |
| 763 | ** WEBPAGE: mlink |
| 764 | ** URL: /mlink?name=FILENAME |
| @@ -934,7 +934,7 @@ | |
| 934 | db_finalize(&q); |
| 935 | @ </tbody> |
| 936 | @ </table> |
| 937 | @ </div> |
| 938 | } |
| 939 | style_footer(); |
| 940 | } |
| 941 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -367,11 +367,11 @@ | |
| 367 | ridFrom = name_to_rid_www("from"); |
| 368 | zPrevDate[0] = 0; |
| 369 | cookie_render(); |
| 370 | if( fnid==0 ){ |
| 371 | @ No such file: %h(zFilename) |
| 372 | style_finish_page("finfo"); |
| 373 | return; |
| 374 | } |
| 375 | if( g.perm.Admin ){ |
| 376 | style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename); |
| 377 | } |
| @@ -754,11 +754,11 @@ | |
| 754 | @ <td></td><td></td><td></td></tr> |
| 755 | } |
| 756 | } |
| 757 | @ </table> |
| 758 | timeline_output_graph_javascript(pGraph, TIMELINE_FILEDIFF, iTableId); |
| 759 | style_finish_page("finfo"); |
| 760 | } |
| 761 | |
| 762 | /* |
| 763 | ** WEBPAGE: mlink |
| 764 | ** URL: /mlink?name=FILENAME |
| @@ -934,7 +934,7 @@ | |
| 934 | db_finalize(&q); |
| 935 | @ </tbody> |
| 936 | @ </table> |
| 937 | @ </div> |
| 938 | } |
| 939 | style_finish_page("finfo"); |
| 940 | } |
| 941 |
+6
-6
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -878,11 +878,11 @@ | ||
| 878 | 878 | /* Emit Forum Javascript. */ |
| 879 | 879 | builtin_request_js("forum.js"); |
| 880 | 880 | forum_emit_js(); |
| 881 | 881 | |
| 882 | 882 | /* Emit the page style. */ |
| 883 | - style_footer(); | |
| 883 | + style_finish_page("forum"); | |
| 884 | 884 | } |
| 885 | 885 | |
| 886 | 886 | /* |
| 887 | 887 | ** Return true if a forum post should be moderated. |
| 888 | 888 | */ |
| @@ -1074,11 +1074,11 @@ | ||
| 1074 | 1074 | @ <input type="submit" value="Login"> |
| 1075 | 1075 | @ </form> |
| 1076 | 1076 | @ <td>Log into an existing account |
| 1077 | 1077 | @ </table> |
| 1078 | 1078 | forum_emit_js(); |
| 1079 | - style_footer(); | |
| 1079 | + style_finish_page("forum"); | |
| 1080 | 1080 | fossil_free(zGoto); |
| 1081 | 1081 | } |
| 1082 | 1082 | |
| 1083 | 1083 | /* |
| 1084 | 1084 | ** Write the "From: USER" line on the webpage. |
| @@ -1135,11 +1135,11 @@ | ||
| 1135 | 1135 | @ Show query parameters</label> |
| 1136 | 1136 | @ </div> |
| 1137 | 1137 | } |
| 1138 | 1138 | @ </form> |
| 1139 | 1139 | forum_emit_js(); |
| 1140 | - style_footer(); | |
| 1140 | + style_finish_page("forum"); | |
| 1141 | 1141 | } |
| 1142 | 1142 | |
| 1143 | 1143 | /* |
| 1144 | 1144 | ** WEBPAGE: forume2 |
| 1145 | 1145 | ** |
| @@ -1315,11 +1315,11 @@ | ||
| 1315 | 1315 | @ Show query parameters</label> |
| 1316 | 1316 | @ </div> |
| 1317 | 1317 | } |
| 1318 | 1318 | @ </form> |
| 1319 | 1319 | forum_emit_js(); |
| 1320 | - style_footer(); | |
| 1320 | + style_finish_page("forum"); | |
| 1321 | 1321 | } |
| 1322 | 1322 | |
| 1323 | 1323 | /* |
| 1324 | 1324 | ** WEBPAGE: forummain |
| 1325 | 1325 | ** WEBPAGE: forum |
| @@ -1357,11 +1357,11 @@ | ||
| 1357 | 1357 | style_submenu_element("Moderation Requests", "%R/modreq"); |
| 1358 | 1358 | } |
| 1359 | 1359 | if( (srchFlags & SRCH_FORUM)!=0 ){ |
| 1360 | 1360 | if( search_screen(SRCH_FORUM, 0) ){ |
| 1361 | 1361 | style_submenu_element("Recent Threads","%R/forum"); |
| 1362 | - style_footer(); | |
| 1362 | + style_finish_page("forum"); | |
| 1363 | 1363 | return; |
| 1364 | 1364 | } |
| 1365 | 1365 | } |
| 1366 | 1366 | iLimit = atoi(PD("n","25")); |
| 1367 | 1367 | iOfst = atoi(PD("x","0")); |
| @@ -1450,7 +1450,7 @@ | ||
| 1450 | 1450 | if( iCnt>0 ){ |
| 1451 | 1451 | @ </table></div> |
| 1452 | 1452 | }else{ |
| 1453 | 1453 | @ <h1>No forum posts found</h1> |
| 1454 | 1454 | } |
| 1455 | - style_footer(); | |
| 1455 | + style_finish_page("forum"); | |
| 1456 | 1456 | } |
| 1457 | 1457 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -878,11 +878,11 @@ | |
| 878 | /* Emit Forum Javascript. */ |
| 879 | builtin_request_js("forum.js"); |
| 880 | forum_emit_js(); |
| 881 | |
| 882 | /* Emit the page style. */ |
| 883 | style_footer(); |
| 884 | } |
| 885 | |
| 886 | /* |
| 887 | ** Return true if a forum post should be moderated. |
| 888 | */ |
| @@ -1074,11 +1074,11 @@ | |
| 1074 | @ <input type="submit" value="Login"> |
| 1075 | @ </form> |
| 1076 | @ <td>Log into an existing account |
| 1077 | @ </table> |
| 1078 | forum_emit_js(); |
| 1079 | style_footer(); |
| 1080 | fossil_free(zGoto); |
| 1081 | } |
| 1082 | |
| 1083 | /* |
| 1084 | ** Write the "From: USER" line on the webpage. |
| @@ -1135,11 +1135,11 @@ | |
| 1135 | @ Show query parameters</label> |
| 1136 | @ </div> |
| 1137 | } |
| 1138 | @ </form> |
| 1139 | forum_emit_js(); |
| 1140 | style_footer(); |
| 1141 | } |
| 1142 | |
| 1143 | /* |
| 1144 | ** WEBPAGE: forume2 |
| 1145 | ** |
| @@ -1315,11 +1315,11 @@ | |
| 1315 | @ Show query parameters</label> |
| 1316 | @ </div> |
| 1317 | } |
| 1318 | @ </form> |
| 1319 | forum_emit_js(); |
| 1320 | style_footer(); |
| 1321 | } |
| 1322 | |
| 1323 | /* |
| 1324 | ** WEBPAGE: forummain |
| 1325 | ** WEBPAGE: forum |
| @@ -1357,11 +1357,11 @@ | |
| 1357 | style_submenu_element("Moderation Requests", "%R/modreq"); |
| 1358 | } |
| 1359 | if( (srchFlags & SRCH_FORUM)!=0 ){ |
| 1360 | if( search_screen(SRCH_FORUM, 0) ){ |
| 1361 | style_submenu_element("Recent Threads","%R/forum"); |
| 1362 | style_footer(); |
| 1363 | return; |
| 1364 | } |
| 1365 | } |
| 1366 | iLimit = atoi(PD("n","25")); |
| 1367 | iOfst = atoi(PD("x","0")); |
| @@ -1450,7 +1450,7 @@ | |
| 1450 | if( iCnt>0 ){ |
| 1451 | @ </table></div> |
| 1452 | }else{ |
| 1453 | @ <h1>No forum posts found</h1> |
| 1454 | } |
| 1455 | style_footer(); |
| 1456 | } |
| 1457 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -878,11 +878,11 @@ | |
| 878 | /* Emit Forum Javascript. */ |
| 879 | builtin_request_js("forum.js"); |
| 880 | forum_emit_js(); |
| 881 | |
| 882 | /* Emit the page style. */ |
| 883 | style_finish_page("forum"); |
| 884 | } |
| 885 | |
| 886 | /* |
| 887 | ** Return true if a forum post should be moderated. |
| 888 | */ |
| @@ -1074,11 +1074,11 @@ | |
| 1074 | @ <input type="submit" value="Login"> |
| 1075 | @ </form> |
| 1076 | @ <td>Log into an existing account |
| 1077 | @ </table> |
| 1078 | forum_emit_js(); |
| 1079 | style_finish_page("forum"); |
| 1080 | fossil_free(zGoto); |
| 1081 | } |
| 1082 | |
| 1083 | /* |
| 1084 | ** Write the "From: USER" line on the webpage. |
| @@ -1135,11 +1135,11 @@ | |
| 1135 | @ Show query parameters</label> |
| 1136 | @ </div> |
| 1137 | } |
| 1138 | @ </form> |
| 1139 | forum_emit_js(); |
| 1140 | style_finish_page("forum"); |
| 1141 | } |
| 1142 | |
| 1143 | /* |
| 1144 | ** WEBPAGE: forume2 |
| 1145 | ** |
| @@ -1315,11 +1315,11 @@ | |
| 1315 | @ Show query parameters</label> |
| 1316 | @ </div> |
| 1317 | } |
| 1318 | @ </form> |
| 1319 | forum_emit_js(); |
| 1320 | style_finish_page("forum"); |
| 1321 | } |
| 1322 | |
| 1323 | /* |
| 1324 | ** WEBPAGE: forummain |
| 1325 | ** WEBPAGE: forum |
| @@ -1357,11 +1357,11 @@ | |
| 1357 | style_submenu_element("Moderation Requests", "%R/modreq"); |
| 1358 | } |
| 1359 | if( (srchFlags & SRCH_FORUM)!=0 ){ |
| 1360 | if( search_screen(SRCH_FORUM, 0) ){ |
| 1361 | style_submenu_element("Recent Threads","%R/forum"); |
| 1362 | style_finish_page("forum"); |
| 1363 | return; |
| 1364 | } |
| 1365 | } |
| 1366 | iLimit = atoi(PD("n","25")); |
| 1367 | iOfst = atoi(PD("x","0")); |
| @@ -1450,7 +1450,7 @@ | |
| 1450 | if( iCnt>0 ){ |
| 1451 | @ </table></div> |
| 1452 | }else{ |
| 1453 | @ <h1>No forum posts found</h1> |
| 1454 | } |
| 1455 | style_finish_page("forum"); |
| 1456 | } |
| 1457 |
+1
-1
| --- src/fossil.page.forumpost.js | ||
| +++ src/fossil.page.forumpost.js | ||
| @@ -45,11 +45,11 @@ | ||
| 45 | 45 | /* Adds an Expand/Collapse toggle to all div.forumPostBody |
| 46 | 46 | elements which are deemed "too large" (those for which |
| 47 | 47 | scrolling is currently activated because they are taller than |
| 48 | 48 | their max-height). */ |
| 49 | 49 | document.querySelectorAll( |
| 50 | - 'div.forumHier, div.forumTime, div.forumHierRoot, div.forumEdit' | |
| 50 | + 'div.forumTime, div.forumEdit' | |
| 51 | 51 | ).forEach(function f(forumPostWrapper){ |
| 52 | 52 | const content = forumPostWrapper.querySelector('div.forumPostBody'); |
| 53 | 53 | if(!content || !scrollbarIsVisible(content)) return; |
| 54 | 54 | const parent = content.parentElement, |
| 55 | 55 | widget = D.addClass( |
| 56 | 56 |
| --- src/fossil.page.forumpost.js | |
| +++ src/fossil.page.forumpost.js | |
| @@ -45,11 +45,11 @@ | |
| 45 | /* Adds an Expand/Collapse toggle to all div.forumPostBody |
| 46 | elements which are deemed "too large" (those for which |
| 47 | scrolling is currently activated because they are taller than |
| 48 | their max-height). */ |
| 49 | document.querySelectorAll( |
| 50 | 'div.forumHier, div.forumTime, div.forumHierRoot, div.forumEdit' |
| 51 | ).forEach(function f(forumPostWrapper){ |
| 52 | const content = forumPostWrapper.querySelector('div.forumPostBody'); |
| 53 | if(!content || !scrollbarIsVisible(content)) return; |
| 54 | const parent = content.parentElement, |
| 55 | widget = D.addClass( |
| 56 |
| --- src/fossil.page.forumpost.js | |
| +++ src/fossil.page.forumpost.js | |
| @@ -45,11 +45,11 @@ | |
| 45 | /* Adds an Expand/Collapse toggle to all div.forumPostBody |
| 46 | elements which are deemed "too large" (those for which |
| 47 | scrolling is currently activated because they are taller than |
| 48 | their max-height). */ |
| 49 | document.querySelectorAll( |
| 50 | 'div.forumTime, div.forumEdit' |
| 51 | ).forEach(function f(forumPostWrapper){ |
| 52 | const content = forumPostWrapper.querySelector('div.forumPostBody'); |
| 53 | if(!content || !scrollbarIsVisible(content)) return; |
| 54 | const parent = content.parentElement, |
| 55 | widget = D.addClass( |
| 56 |
+16
-16
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -503,11 +503,11 @@ | ||
| 503 | 503 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 504 | 504 | rid = name_to_rid_www("name"); |
| 505 | 505 | if( rid==0 ){ |
| 506 | 506 | style_header("Check-in Information Error"); |
| 507 | 507 | @ No such object: %h(g.argv[2]) |
| 508 | - style_footer(); | |
| 508 | + style_finish_page("ci_tags"); | |
| 509 | 509 | return; |
| 510 | 510 | } |
| 511 | 511 | zHash = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 512 | 512 | style_header("Tags and Properties"); |
| 513 | 513 | @ <h1>Tags and Properties for Check-In \ |
| @@ -595,11 +595,11 @@ | ||
| 595 | 595 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 596 | 596 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 597 | 597 | www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL, |
| 598 | 598 | 0, 0, 0, rid, 0, 0); |
| 599 | 599 | db_finalize(&q); |
| 600 | - style_footer(); | |
| 600 | + style_finish_page("ci_tags"); | |
| 601 | 601 | } |
| 602 | 602 | |
| 603 | 603 | /* |
| 604 | 604 | ** WEBPAGE: vinfo |
| 605 | 605 | ** WEBPAGE: ci |
| @@ -634,11 +634,11 @@ | ||
| 634 | 634 | zName = P("name"); |
| 635 | 635 | rid = name_to_rid_www("name"); |
| 636 | 636 | if( rid==0 ){ |
| 637 | 637 | style_header("Check-in Information Error"); |
| 638 | 638 | @ No such object: %h(g.argv[2]) |
| 639 | - style_footer(); | |
| 639 | + style_finish_page("vinfo"); | |
| 640 | 640 | return; |
| 641 | 641 | } |
| 642 | 642 | zRe = P("regex"); |
| 643 | 643 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 644 | 644 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -940,11 +940,11 @@ | ||
| 940 | 940 | diffFlags,pRe,mperm); |
| 941 | 941 | } |
| 942 | 942 | db_finalize(&q3); |
| 943 | 943 | append_diff_javascript(diffType==2); |
| 944 | 944 | cookie_render(); |
| 945 | - style_footer(); | |
| 945 | + style_finish_page("vinfo"); | |
| 946 | 946 | } |
| 947 | 947 | |
| 948 | 948 | /* |
| 949 | 949 | ** WEBPAGE: winfo |
| 950 | 950 | ** URL: /winfo?name=HASH |
| @@ -966,11 +966,11 @@ | ||
| 966 | 966 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 967 | 967 | rid = name_to_rid_www("name"); |
| 968 | 968 | if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){ |
| 969 | 969 | style_header("Wiki Page Information Error"); |
| 970 | 970 | @ No such object: %h(P("name")) |
| 971 | - style_footer(); | |
| 971 | + style_finish_page("winfo"); | |
| 972 | 972 | return; |
| 973 | 973 | } |
| 974 | 974 | if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){ |
| 975 | 975 | if( strcmp(zModAction,"delete")==0 ){ |
| 976 | 976 | moderation_disapprove(rid); |
| @@ -1054,11 +1054,11 @@ | ||
| 1054 | 1054 | safe_html_context(DOCSRC_WIKI); |
| 1055 | 1055 | wiki_render_by_mimetype(&wiki, pWiki->zMimetype); |
| 1056 | 1056 | blob_reset(&wiki); |
| 1057 | 1057 | manifest_destroy(pWiki); |
| 1058 | 1058 | document_emit_js(); |
| 1059 | - style_footer(); | |
| 1059 | + style_finish_page("winfo"); | |
| 1060 | 1060 | } |
| 1061 | 1061 | |
| 1062 | 1062 | /* |
| 1063 | 1063 | ** Find an check-in based on query parameter zParam and parse its |
| 1064 | 1064 | ** manifest. Return the number of errors. |
| @@ -1327,11 +1327,11 @@ | ||
| 1327 | 1327 | } |
| 1328 | 1328 | } |
| 1329 | 1329 | manifest_destroy(pFrom); |
| 1330 | 1330 | manifest_destroy(pTo); |
| 1331 | 1331 | append_diff_javascript(diffType==2); |
| 1332 | - style_footer(); | |
| 1332 | + style_finish_page("vdiff"); | |
| 1333 | 1333 | } |
| 1334 | 1334 | |
| 1335 | 1335 | #if INTERFACE |
| 1336 | 1336 | /* |
| 1337 | 1337 | ** Possible return values from object_description() |
| @@ -1761,11 +1761,11 @@ | ||
| 1761 | 1761 | @ are shown.</b> |
| 1762 | 1762 | } |
| 1763 | 1763 | @ <hr /> |
| 1764 | 1764 | append_diff(zV1, zV2, diffFlags, pRe); |
| 1765 | 1765 | append_diff_javascript(diffType); |
| 1766 | - style_footer(); | |
| 1766 | + style_finish_page("fdiff"); | |
| 1767 | 1767 | } |
| 1768 | 1768 | |
| 1769 | 1769 | /* |
| 1770 | 1770 | ** WEBPAGE: raw |
| 1771 | 1771 | ** URL: /raw/ARTIFACTID |
| @@ -1965,11 +1965,11 @@ | ||
| 1965 | 1965 | @ <hr /> |
| 1966 | 1966 | content_get(rid, &content); |
| 1967 | 1967 | @ <blockquote><pre> |
| 1968 | 1968 | hexdump(&content); |
| 1969 | 1969 | @ </pre></blockquote> |
| 1970 | - style_footer(); | |
| 1970 | + style_finish_page("hexdump"); | |
| 1971 | 1971 | } |
| 1972 | 1972 | |
| 1973 | 1973 | /* |
| 1974 | 1974 | ** Look for "ci" and "filename" query parameters. If found, try to |
| 1975 | 1975 | ** use them to extract the record ID of an artifact for the file. |
| @@ -2263,11 +2263,11 @@ | ||
| 2263 | 2263 | page_tree(); |
| 2264 | 2264 | return; |
| 2265 | 2265 | } |
| 2266 | 2266 | style_header("Missing name= query parameter"); |
| 2267 | 2267 | @ The name= query parameter is missing |
| 2268 | - style_footer(); | |
| 2268 | + style_finish_page("artifact"); | |
| 2269 | 2269 | return; |
| 2270 | 2270 | } |
| 2271 | 2271 | |
| 2272 | 2272 | url_initialize(&url, g.zPath); |
| 2273 | 2273 | url_add_parameter(&url, "name", zName); |
| @@ -2324,11 +2324,11 @@ | ||
| 2324 | 2324 | }else{ |
| 2325 | 2325 | style_header("No such artifact"); |
| 2326 | 2326 | @ Artifact '%h(zName)' does not exist in this repository. |
| 2327 | 2327 | } |
| 2328 | 2328 | if( rid==0 ){ |
| 2329 | - style_footer(); | |
| 2329 | + style_finish_page("artifact"); | |
| 2330 | 2330 | return; |
| 2331 | 2331 | } |
| 2332 | 2332 | } |
| 2333 | 2333 | |
| 2334 | 2334 | if( descOnly || P("verbose")!=0 ){ |
| @@ -2529,11 +2529,11 @@ | ||
| 2529 | 2529 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 2530 | 2530 | } |
| 2531 | 2531 | @ </blockquote> |
| 2532 | 2532 | } |
| 2533 | 2533 | } |
| 2534 | - style_footer(); | |
| 2534 | + style_finish_page("artifact"); | |
| 2535 | 2535 | } |
| 2536 | 2536 | |
| 2537 | 2537 | /* |
| 2538 | 2538 | ** WEBPAGE: tinfo |
| 2539 | 2539 | ** URL: /tinfo?name=ARTIFACTID |
| @@ -2636,11 +2636,11 @@ | ||
| 2636 | 2636 | |
| 2637 | 2637 | @ <div class="section">Changes</div> |
| 2638 | 2638 | @ <p> |
| 2639 | 2639 | ticket_output_change_artifact(pTktChng, 0, 1); |
| 2640 | 2640 | manifest_destroy(pTktChng); |
| 2641 | - style_footer(); | |
| 2641 | + style_finish_page("tinfo"); | |
| 2642 | 2642 | } |
| 2643 | 2643 | |
| 2644 | 2644 | |
| 2645 | 2645 | /* |
| 2646 | 2646 | ** WEBPAGE: info |
| @@ -2687,11 +2687,11 @@ | ||
| 2687 | 2687 | @ <p>No such object: %h(zName)</p> |
| 2688 | 2688 | if( nLen<4 ){ |
| 2689 | 2689 | @ <p>Object name should be no less than 4 characters. Ten or more |
| 2690 | 2690 | @ characters are recommended.</p> |
| 2691 | 2691 | } |
| 2692 | - style_footer(); | |
| 2692 | + style_finish_page("info"); | |
| 2693 | 2693 | return; |
| 2694 | 2694 | }else if( rc==2 ){ |
| 2695 | 2695 | cgi_set_parameter("src","info"); |
| 2696 | 2696 | ambiguous_page(); |
| 2697 | 2697 | return; |
| @@ -2699,11 +2699,11 @@ | ||
| 2699 | 2699 | zName = blob_str(&uuid); |
| 2700 | 2700 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName); |
| 2701 | 2701 | if( rid==0 ){ |
| 2702 | 2702 | style_header("Broken Link"); |
| 2703 | 2703 | @ <p>No such object: %h(zName)</p> |
| 2704 | - style_footer(); | |
| 2704 | + style_finish_page("info"); | |
| 2705 | 2705 | return; |
| 2706 | 2706 | } |
| 2707 | 2707 | if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ |
| 2708 | 2708 | ci_page(); |
| 2709 | 2709 | }else |
| @@ -3224,11 +3224,11 @@ | ||
| 3224 | 3224 | } |
| 3225 | 3225 | @ </td></tr> |
| 3226 | 3226 | @ </table> |
| 3227 | 3227 | @ </div></form> |
| 3228 | 3228 | builtin_request_js("ci_edit.js"); |
| 3229 | - style_footer(); | |
| 3229 | + style_finish_page("ci_edit"); | |
| 3230 | 3230 | } |
| 3231 | 3231 | |
| 3232 | 3232 | /* |
| 3233 | 3233 | ** Prepare an ammended commit comment. Let the user modify it using the |
| 3234 | 3234 | ** editor specified in the global_config table or either |
| 3235 | 3235 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -503,11 +503,11 @@ | |
| 503 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 504 | rid = name_to_rid_www("name"); |
| 505 | if( rid==0 ){ |
| 506 | style_header("Check-in Information Error"); |
| 507 | @ No such object: %h(g.argv[2]) |
| 508 | style_footer(); |
| 509 | return; |
| 510 | } |
| 511 | zHash = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 512 | style_header("Tags and Properties"); |
| 513 | @ <h1>Tags and Properties for Check-In \ |
| @@ -595,11 +595,11 @@ | |
| 595 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 596 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 597 | www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL, |
| 598 | 0, 0, 0, rid, 0, 0); |
| 599 | db_finalize(&q); |
| 600 | style_footer(); |
| 601 | } |
| 602 | |
| 603 | /* |
| 604 | ** WEBPAGE: vinfo |
| 605 | ** WEBPAGE: ci |
| @@ -634,11 +634,11 @@ | |
| 634 | zName = P("name"); |
| 635 | rid = name_to_rid_www("name"); |
| 636 | if( rid==0 ){ |
| 637 | style_header("Check-in Information Error"); |
| 638 | @ No such object: %h(g.argv[2]) |
| 639 | style_footer(); |
| 640 | return; |
| 641 | } |
| 642 | zRe = P("regex"); |
| 643 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 644 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -940,11 +940,11 @@ | |
| 940 | diffFlags,pRe,mperm); |
| 941 | } |
| 942 | db_finalize(&q3); |
| 943 | append_diff_javascript(diffType==2); |
| 944 | cookie_render(); |
| 945 | style_footer(); |
| 946 | } |
| 947 | |
| 948 | /* |
| 949 | ** WEBPAGE: winfo |
| 950 | ** URL: /winfo?name=HASH |
| @@ -966,11 +966,11 @@ | |
| 966 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 967 | rid = name_to_rid_www("name"); |
| 968 | if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){ |
| 969 | style_header("Wiki Page Information Error"); |
| 970 | @ No such object: %h(P("name")) |
| 971 | style_footer(); |
| 972 | return; |
| 973 | } |
| 974 | if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){ |
| 975 | if( strcmp(zModAction,"delete")==0 ){ |
| 976 | moderation_disapprove(rid); |
| @@ -1054,11 +1054,11 @@ | |
| 1054 | safe_html_context(DOCSRC_WIKI); |
| 1055 | wiki_render_by_mimetype(&wiki, pWiki->zMimetype); |
| 1056 | blob_reset(&wiki); |
| 1057 | manifest_destroy(pWiki); |
| 1058 | document_emit_js(); |
| 1059 | style_footer(); |
| 1060 | } |
| 1061 | |
| 1062 | /* |
| 1063 | ** Find an check-in based on query parameter zParam and parse its |
| 1064 | ** manifest. Return the number of errors. |
| @@ -1327,11 +1327,11 @@ | |
| 1327 | } |
| 1328 | } |
| 1329 | manifest_destroy(pFrom); |
| 1330 | manifest_destroy(pTo); |
| 1331 | append_diff_javascript(diffType==2); |
| 1332 | style_footer(); |
| 1333 | } |
| 1334 | |
| 1335 | #if INTERFACE |
| 1336 | /* |
| 1337 | ** Possible return values from object_description() |
| @@ -1761,11 +1761,11 @@ | |
| 1761 | @ are shown.</b> |
| 1762 | } |
| 1763 | @ <hr /> |
| 1764 | append_diff(zV1, zV2, diffFlags, pRe); |
| 1765 | append_diff_javascript(diffType); |
| 1766 | style_footer(); |
| 1767 | } |
| 1768 | |
| 1769 | /* |
| 1770 | ** WEBPAGE: raw |
| 1771 | ** URL: /raw/ARTIFACTID |
| @@ -1965,11 +1965,11 @@ | |
| 1965 | @ <hr /> |
| 1966 | content_get(rid, &content); |
| 1967 | @ <blockquote><pre> |
| 1968 | hexdump(&content); |
| 1969 | @ </pre></blockquote> |
| 1970 | style_footer(); |
| 1971 | } |
| 1972 | |
| 1973 | /* |
| 1974 | ** Look for "ci" and "filename" query parameters. If found, try to |
| 1975 | ** use them to extract the record ID of an artifact for the file. |
| @@ -2263,11 +2263,11 @@ | |
| 2263 | page_tree(); |
| 2264 | return; |
| 2265 | } |
| 2266 | style_header("Missing name= query parameter"); |
| 2267 | @ The name= query parameter is missing |
| 2268 | style_footer(); |
| 2269 | return; |
| 2270 | } |
| 2271 | |
| 2272 | url_initialize(&url, g.zPath); |
| 2273 | url_add_parameter(&url, "name", zName); |
| @@ -2324,11 +2324,11 @@ | |
| 2324 | }else{ |
| 2325 | style_header("No such artifact"); |
| 2326 | @ Artifact '%h(zName)' does not exist in this repository. |
| 2327 | } |
| 2328 | if( rid==0 ){ |
| 2329 | style_footer(); |
| 2330 | return; |
| 2331 | } |
| 2332 | } |
| 2333 | |
| 2334 | if( descOnly || P("verbose")!=0 ){ |
| @@ -2529,11 +2529,11 @@ | |
| 2529 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 2530 | } |
| 2531 | @ </blockquote> |
| 2532 | } |
| 2533 | } |
| 2534 | style_footer(); |
| 2535 | } |
| 2536 | |
| 2537 | /* |
| 2538 | ** WEBPAGE: tinfo |
| 2539 | ** URL: /tinfo?name=ARTIFACTID |
| @@ -2636,11 +2636,11 @@ | |
| 2636 | |
| 2637 | @ <div class="section">Changes</div> |
| 2638 | @ <p> |
| 2639 | ticket_output_change_artifact(pTktChng, 0, 1); |
| 2640 | manifest_destroy(pTktChng); |
| 2641 | style_footer(); |
| 2642 | } |
| 2643 | |
| 2644 | |
| 2645 | /* |
| 2646 | ** WEBPAGE: info |
| @@ -2687,11 +2687,11 @@ | |
| 2687 | @ <p>No such object: %h(zName)</p> |
| 2688 | if( nLen<4 ){ |
| 2689 | @ <p>Object name should be no less than 4 characters. Ten or more |
| 2690 | @ characters are recommended.</p> |
| 2691 | } |
| 2692 | style_footer(); |
| 2693 | return; |
| 2694 | }else if( rc==2 ){ |
| 2695 | cgi_set_parameter("src","info"); |
| 2696 | ambiguous_page(); |
| 2697 | return; |
| @@ -2699,11 +2699,11 @@ | |
| 2699 | zName = blob_str(&uuid); |
| 2700 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName); |
| 2701 | if( rid==0 ){ |
| 2702 | style_header("Broken Link"); |
| 2703 | @ <p>No such object: %h(zName)</p> |
| 2704 | style_footer(); |
| 2705 | return; |
| 2706 | } |
| 2707 | if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ |
| 2708 | ci_page(); |
| 2709 | }else |
| @@ -3224,11 +3224,11 @@ | |
| 3224 | } |
| 3225 | @ </td></tr> |
| 3226 | @ </table> |
| 3227 | @ </div></form> |
| 3228 | builtin_request_js("ci_edit.js"); |
| 3229 | style_footer(); |
| 3230 | } |
| 3231 | |
| 3232 | /* |
| 3233 | ** Prepare an ammended commit comment. Let the user modify it using the |
| 3234 | ** editor specified in the global_config table or either |
| 3235 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -503,11 +503,11 @@ | |
| 503 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 504 | rid = name_to_rid_www("name"); |
| 505 | if( rid==0 ){ |
| 506 | style_header("Check-in Information Error"); |
| 507 | @ No such object: %h(g.argv[2]) |
| 508 | style_finish_page("ci_tags"); |
| 509 | return; |
| 510 | } |
| 511 | zHash = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 512 | style_header("Tags and Properties"); |
| 513 | @ <h1>Tags and Properties for Check-In \ |
| @@ -595,11 +595,11 @@ | |
| 595 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 596 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 597 | www_print_timeline(&q, TIMELINE_DISJOINT|TIMELINE_GRAPH|TIMELINE_NOSCROLL, |
| 598 | 0, 0, 0, rid, 0, 0); |
| 599 | db_finalize(&q); |
| 600 | style_finish_page("ci_tags"); |
| 601 | } |
| 602 | |
| 603 | /* |
| 604 | ** WEBPAGE: vinfo |
| 605 | ** WEBPAGE: ci |
| @@ -634,11 +634,11 @@ | |
| 634 | zName = P("name"); |
| 635 | rid = name_to_rid_www("name"); |
| 636 | if( rid==0 ){ |
| 637 | style_header("Check-in Information Error"); |
| 638 | @ No such object: %h(g.argv[2]) |
| 639 | style_finish_page("vinfo"); |
| 640 | return; |
| 641 | } |
| 642 | zRe = P("regex"); |
| 643 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 644 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -940,11 +940,11 @@ | |
| 940 | diffFlags,pRe,mperm); |
| 941 | } |
| 942 | db_finalize(&q3); |
| 943 | append_diff_javascript(diffType==2); |
| 944 | cookie_render(); |
| 945 | style_finish_page("vinfo"); |
| 946 | } |
| 947 | |
| 948 | /* |
| 949 | ** WEBPAGE: winfo |
| 950 | ** URL: /winfo?name=HASH |
| @@ -966,11 +966,11 @@ | |
| 966 | if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } |
| 967 | rid = name_to_rid_www("name"); |
| 968 | if( rid==0 || (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))==0 ){ |
| 969 | style_header("Wiki Page Information Error"); |
| 970 | @ No such object: %h(P("name")) |
| 971 | style_finish_page("winfo"); |
| 972 | return; |
| 973 | } |
| 974 | if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){ |
| 975 | if( strcmp(zModAction,"delete")==0 ){ |
| 976 | moderation_disapprove(rid); |
| @@ -1054,11 +1054,11 @@ | |
| 1054 | safe_html_context(DOCSRC_WIKI); |
| 1055 | wiki_render_by_mimetype(&wiki, pWiki->zMimetype); |
| 1056 | blob_reset(&wiki); |
| 1057 | manifest_destroy(pWiki); |
| 1058 | document_emit_js(); |
| 1059 | style_finish_page("winfo"); |
| 1060 | } |
| 1061 | |
| 1062 | /* |
| 1063 | ** Find an check-in based on query parameter zParam and parse its |
| 1064 | ** manifest. Return the number of errors. |
| @@ -1327,11 +1327,11 @@ | |
| 1327 | } |
| 1328 | } |
| 1329 | manifest_destroy(pFrom); |
| 1330 | manifest_destroy(pTo); |
| 1331 | append_diff_javascript(diffType==2); |
| 1332 | style_finish_page("vdiff"); |
| 1333 | } |
| 1334 | |
| 1335 | #if INTERFACE |
| 1336 | /* |
| 1337 | ** Possible return values from object_description() |
| @@ -1761,11 +1761,11 @@ | |
| 1761 | @ are shown.</b> |
| 1762 | } |
| 1763 | @ <hr /> |
| 1764 | append_diff(zV1, zV2, diffFlags, pRe); |
| 1765 | append_diff_javascript(diffType); |
| 1766 | style_finish_page("fdiff"); |
| 1767 | } |
| 1768 | |
| 1769 | /* |
| 1770 | ** WEBPAGE: raw |
| 1771 | ** URL: /raw/ARTIFACTID |
| @@ -1965,11 +1965,11 @@ | |
| 1965 | @ <hr /> |
| 1966 | content_get(rid, &content); |
| 1967 | @ <blockquote><pre> |
| 1968 | hexdump(&content); |
| 1969 | @ </pre></blockquote> |
| 1970 | style_finish_page("hexdump"); |
| 1971 | } |
| 1972 | |
| 1973 | /* |
| 1974 | ** Look for "ci" and "filename" query parameters. If found, try to |
| 1975 | ** use them to extract the record ID of an artifact for the file. |
| @@ -2263,11 +2263,11 @@ | |
| 2263 | page_tree(); |
| 2264 | return; |
| 2265 | } |
| 2266 | style_header("Missing name= query parameter"); |
| 2267 | @ The name= query parameter is missing |
| 2268 | style_finish_page("artifact"); |
| 2269 | return; |
| 2270 | } |
| 2271 | |
| 2272 | url_initialize(&url, g.zPath); |
| 2273 | url_add_parameter(&url, "name", zName); |
| @@ -2324,11 +2324,11 @@ | |
| 2324 | }else{ |
| 2325 | style_header("No such artifact"); |
| 2326 | @ Artifact '%h(zName)' does not exist in this repository. |
| 2327 | } |
| 2328 | if( rid==0 ){ |
| 2329 | style_finish_page("artifact"); |
| 2330 | return; |
| 2331 | } |
| 2332 | } |
| 2333 | |
| 2334 | if( descOnly || P("verbose")!=0 ){ |
| @@ -2529,11 +2529,11 @@ | |
| 2529 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 2530 | } |
| 2531 | @ </blockquote> |
| 2532 | } |
| 2533 | } |
| 2534 | style_finish_page("artifact"); |
| 2535 | } |
| 2536 | |
| 2537 | /* |
| 2538 | ** WEBPAGE: tinfo |
| 2539 | ** URL: /tinfo?name=ARTIFACTID |
| @@ -2636,11 +2636,11 @@ | |
| 2636 | |
| 2637 | @ <div class="section">Changes</div> |
| 2638 | @ <p> |
| 2639 | ticket_output_change_artifact(pTktChng, 0, 1); |
| 2640 | manifest_destroy(pTktChng); |
| 2641 | style_finish_page("tinfo"); |
| 2642 | } |
| 2643 | |
| 2644 | |
| 2645 | /* |
| 2646 | ** WEBPAGE: info |
| @@ -2687,11 +2687,11 @@ | |
| 2687 | @ <p>No such object: %h(zName)</p> |
| 2688 | if( nLen<4 ){ |
| 2689 | @ <p>Object name should be no less than 4 characters. Ten or more |
| 2690 | @ characters are recommended.</p> |
| 2691 | } |
| 2692 | style_finish_page("info"); |
| 2693 | return; |
| 2694 | }else if( rc==2 ){ |
| 2695 | cgi_set_parameter("src","info"); |
| 2696 | ambiguous_page(); |
| 2697 | return; |
| @@ -2699,11 +2699,11 @@ | |
| 2699 | zName = blob_str(&uuid); |
| 2700 | rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zName); |
| 2701 | if( rid==0 ){ |
| 2702 | style_header("Broken Link"); |
| 2703 | @ <p>No such object: %h(zName)</p> |
| 2704 | style_finish_page("info"); |
| 2705 | return; |
| 2706 | } |
| 2707 | if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ |
| 2708 | ci_page(); |
| 2709 | }else |
| @@ -3224,11 +3224,11 @@ | |
| 3224 | } |
| 3225 | @ </td></tr> |
| 3226 | @ </table> |
| 3227 | @ </div></form> |
| 3228 | builtin_request_js("ci_edit.js"); |
| 3229 | style_finish_page("ci_edit"); |
| 3230 | } |
| 3231 | |
| 3232 | /* |
| 3233 | ** Prepare an ammended commit comment. Let the user modify it using the |
| 3234 | ** editor specified in the global_config table or either |
| 3235 |
+2
-2
| --- src/interwiki.c | ||
| +++ src/interwiki.c | ||
| @@ -384,11 +384,11 @@ | ||
| 384 | 384 | @ No mappings are currently defined. |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | 387 | if( !g.perm.Setup ){ |
| 388 | 388 | /* Do not show intermap editing fields to non-setup users */ |
| 389 | - style_footer(); | |
| 389 | + style_finish_page("interwiki"); | |
| 390 | 390 | return; |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | 393 | @ <p>To add a new mapping, fill out the form below providing a unique name |
| 394 | 394 | @ for the tag. To edit an exist mapping, fill out the form and use the |
| @@ -417,7 +417,7 @@ | ||
| 417 | 417 | @ <tr><td></td> |
| 418 | 418 | @ <td><input type="submit" name="submit" value="Apply Changes"></td></tr> |
| 419 | 419 | @ </table> |
| 420 | 420 | @ </form> |
| 421 | 421 | |
| 422 | - style_footer(); | |
| 422 | + style_finish_page("interwiki"); | |
| 423 | 423 | } |
| 424 | 424 |
| --- src/interwiki.c | |
| +++ src/interwiki.c | |
| @@ -384,11 +384,11 @@ | |
| 384 | @ No mappings are currently defined. |
| 385 | } |
| 386 | |
| 387 | if( !g.perm.Setup ){ |
| 388 | /* Do not show intermap editing fields to non-setup users */ |
| 389 | style_footer(); |
| 390 | return; |
| 391 | } |
| 392 | |
| 393 | @ <p>To add a new mapping, fill out the form below providing a unique name |
| 394 | @ for the tag. To edit an exist mapping, fill out the form and use the |
| @@ -417,7 +417,7 @@ | |
| 417 | @ <tr><td></td> |
| 418 | @ <td><input type="submit" name="submit" value="Apply Changes"></td></tr> |
| 419 | @ </table> |
| 420 | @ </form> |
| 421 | |
| 422 | style_footer(); |
| 423 | } |
| 424 |
| --- src/interwiki.c | |
| +++ src/interwiki.c | |
| @@ -384,11 +384,11 @@ | |
| 384 | @ No mappings are currently defined. |
| 385 | } |
| 386 | |
| 387 | if( !g.perm.Setup ){ |
| 388 | /* Do not show intermap editing fields to non-setup users */ |
| 389 | style_finish_page("interwiki"); |
| 390 | return; |
| 391 | } |
| 392 | |
| 393 | @ <p>To add a new mapping, fill out the form below providing a unique name |
| 394 | @ for the tag. To edit an exist mapping, fill out the form and use the |
| @@ -417,7 +417,7 @@ | |
| 417 | @ <tr><td></td> |
| 418 | @ <td><input type="submit" name="submit" value="Apply Changes"></td></tr> |
| 419 | @ </table> |
| 420 | @ </form> |
| 421 | |
| 422 | style_finish_page("interwiki"); |
| 423 | } |
| 424 |
+1
-1
| --- src/loadctrl.c | ||
| +++ src/loadctrl.c | ||
| @@ -57,10 +57,10 @@ | ||
| 57 | 57 | style_header("Server Overload"); |
| 58 | 58 | @ <h2>The server load is currently too high. |
| 59 | 59 | @ Please try again later.</h2> |
| 60 | 60 | @ <p>Current load average: %f(load_average()).<br /> |
| 61 | 61 | @ Load average limit: %f(mxLoad)</p> |
| 62 | - style_footer(); | |
| 62 | + style_finish_page("test"); | |
| 63 | 63 | cgi_set_status(503,"Server Overload"); |
| 64 | 64 | cgi_reply(); |
| 65 | 65 | exit(0); |
| 66 | 66 | } |
| 67 | 67 |
| --- src/loadctrl.c | |
| +++ src/loadctrl.c | |
| @@ -57,10 +57,10 @@ | |
| 57 | style_header("Server Overload"); |
| 58 | @ <h2>The server load is currently too high. |
| 59 | @ Please try again later.</h2> |
| 60 | @ <p>Current load average: %f(load_average()).<br /> |
| 61 | @ Load average limit: %f(mxLoad)</p> |
| 62 | style_footer(); |
| 63 | cgi_set_status(503,"Server Overload"); |
| 64 | cgi_reply(); |
| 65 | exit(0); |
| 66 | } |
| 67 |
| --- src/loadctrl.c | |
| +++ src/loadctrl.c | |
| @@ -57,10 +57,10 @@ | |
| 57 | style_header("Server Overload"); |
| 58 | @ <h2>The server load is currently too high. |
| 59 | @ Please try again later.</h2> |
| 60 | @ <p>Current load average: %f(load_average()).<br /> |
| 61 | @ Load average limit: %f(mxLoad)</p> |
| 62 | style_finish_page("test"); |
| 63 | cgi_set_status(503,"Server Overload"); |
| 64 | cgi_reply(); |
| 65 | exit(0); |
| 66 | } |
| 67 |
+4
-4
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -794,11 +794,11 @@ | ||
| 794 | 794 | @ <td><input type="submit" value="Change Password" /></td></tr> |
| 795 | 795 | @ </table> |
| 796 | 796 | @ </form> |
| 797 | 797 | } |
| 798 | 798 | } |
| 799 | - style_footer(); | |
| 799 | + style_finish_page("login"); | |
| 800 | 800 | } |
| 801 | 801 | |
| 802 | 802 | /* |
| 803 | 803 | ** Attempt to find login credentials for user zLogin on a peer repository |
| 804 | 804 | ** with project code zCode. Transfer those credentials to the local |
| @@ -1544,11 +1544,11 @@ | ||
| 1544 | 1544 | int doAlerts = 0; /* True if subscription is wanted too */ |
| 1545 | 1545 | if( !db_get_boolean("self-register", 0) ){ |
| 1546 | 1546 | style_header("Registration not possible"); |
| 1547 | 1547 | @ <p>This project does not allow user self-registration. Please contact the |
| 1548 | 1548 | @ project administrator to obtain an account.</p> |
| 1549 | - style_footer(); | |
| 1549 | + style_finish_page("register"); | |
| 1550 | 1550 | return; |
| 1551 | 1551 | } |
| 1552 | 1552 | zPerms = db_get("default-perms", "u"); |
| 1553 | 1553 | |
| 1554 | 1554 | /* Prompt the user for email alerts if this repository is configured for |
| @@ -1703,11 +1703,11 @@ | ||
| 1703 | 1703 | } |
| 1704 | 1704 | alert_sender_free(pSender); |
| 1705 | 1705 | if( zGoto ){ |
| 1706 | 1706 | @ <p><a href='%h(zGoto)'>Continue</a> |
| 1707 | 1707 | } |
| 1708 | - style_footer(); | |
| 1708 | + style_finish_page("register"); | |
| 1709 | 1709 | return; |
| 1710 | 1710 | } |
| 1711 | 1711 | redirect_to_g(); |
| 1712 | 1712 | } |
| 1713 | 1713 | |
| @@ -1795,11 +1795,11 @@ | ||
| 1795 | 1795 | @ %h(zCaptcha) |
| 1796 | 1796 | @ </pre> |
| 1797 | 1797 | @ Enter this 8-letter code in the "Captcha" box above. |
| 1798 | 1798 | @ </td></tr></table></div> |
| 1799 | 1799 | @ </form> |
| 1800 | - style_footer(); | |
| 1800 | + style_finish_page("register"); | |
| 1801 | 1801 | |
| 1802 | 1802 | free(zCaptcha); |
| 1803 | 1803 | } |
| 1804 | 1804 | |
| 1805 | 1805 | /* |
| 1806 | 1806 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -794,11 +794,11 @@ | |
| 794 | @ <td><input type="submit" value="Change Password" /></td></tr> |
| 795 | @ </table> |
| 796 | @ </form> |
| 797 | } |
| 798 | } |
| 799 | style_footer(); |
| 800 | } |
| 801 | |
| 802 | /* |
| 803 | ** Attempt to find login credentials for user zLogin on a peer repository |
| 804 | ** with project code zCode. Transfer those credentials to the local |
| @@ -1544,11 +1544,11 @@ | |
| 1544 | int doAlerts = 0; /* True if subscription is wanted too */ |
| 1545 | if( !db_get_boolean("self-register", 0) ){ |
| 1546 | style_header("Registration not possible"); |
| 1547 | @ <p>This project does not allow user self-registration. Please contact the |
| 1548 | @ project administrator to obtain an account.</p> |
| 1549 | style_footer(); |
| 1550 | return; |
| 1551 | } |
| 1552 | zPerms = db_get("default-perms", "u"); |
| 1553 | |
| 1554 | /* Prompt the user for email alerts if this repository is configured for |
| @@ -1703,11 +1703,11 @@ | |
| 1703 | } |
| 1704 | alert_sender_free(pSender); |
| 1705 | if( zGoto ){ |
| 1706 | @ <p><a href='%h(zGoto)'>Continue</a> |
| 1707 | } |
| 1708 | style_footer(); |
| 1709 | return; |
| 1710 | } |
| 1711 | redirect_to_g(); |
| 1712 | } |
| 1713 | |
| @@ -1795,11 +1795,11 @@ | |
| 1795 | @ %h(zCaptcha) |
| 1796 | @ </pre> |
| 1797 | @ Enter this 8-letter code in the "Captcha" box above. |
| 1798 | @ </td></tr></table></div> |
| 1799 | @ </form> |
| 1800 | style_footer(); |
| 1801 | |
| 1802 | free(zCaptcha); |
| 1803 | } |
| 1804 | |
| 1805 | /* |
| 1806 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -794,11 +794,11 @@ | |
| 794 | @ <td><input type="submit" value="Change Password" /></td></tr> |
| 795 | @ </table> |
| 796 | @ </form> |
| 797 | } |
| 798 | } |
| 799 | style_finish_page("login"); |
| 800 | } |
| 801 | |
| 802 | /* |
| 803 | ** Attempt to find login credentials for user zLogin on a peer repository |
| 804 | ** with project code zCode. Transfer those credentials to the local |
| @@ -1544,11 +1544,11 @@ | |
| 1544 | int doAlerts = 0; /* True if subscription is wanted too */ |
| 1545 | if( !db_get_boolean("self-register", 0) ){ |
| 1546 | style_header("Registration not possible"); |
| 1547 | @ <p>This project does not allow user self-registration. Please contact the |
| 1548 | @ project administrator to obtain an account.</p> |
| 1549 | style_finish_page("register"); |
| 1550 | return; |
| 1551 | } |
| 1552 | zPerms = db_get("default-perms", "u"); |
| 1553 | |
| 1554 | /* Prompt the user for email alerts if this repository is configured for |
| @@ -1703,11 +1703,11 @@ | |
| 1703 | } |
| 1704 | alert_sender_free(pSender); |
| 1705 | if( zGoto ){ |
| 1706 | @ <p><a href='%h(zGoto)'>Continue</a> |
| 1707 | } |
| 1708 | style_finish_page("register"); |
| 1709 | return; |
| 1710 | } |
| 1711 | redirect_to_g(); |
| 1712 | } |
| 1713 | |
| @@ -1795,11 +1795,11 @@ | |
| 1795 | @ %h(zCaptcha) |
| 1796 | @ </pre> |
| 1797 | @ Enter this 8-letter code in the "Captcha" box above. |
| 1798 | @ </td></tr></table></div> |
| 1799 | @ </form> |
| 1800 | style_finish_page("register"); |
| 1801 | |
| 1802 | free(zCaptcha); |
| 1803 | } |
| 1804 | |
| 1805 | /* |
| 1806 |
+2
-2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -1308,11 +1308,11 @@ | ||
| 1308 | 1308 | style_submenu_element("Stat", "stat"); |
| 1309 | 1309 | fossil_version_blob(&versionInfo, verboseFlag); |
| 1310 | 1310 | @ <pre> |
| 1311 | 1311 | @ %h(blob_str(&versionInfo)) |
| 1312 | 1312 | @ </pre> |
| 1313 | - style_footer(); | |
| 1313 | + style_finish_page("version"); | |
| 1314 | 1314 | } |
| 1315 | 1315 | |
| 1316 | 1316 | |
| 1317 | 1317 | /* |
| 1318 | 1318 | ** Set the g.zBaseURL value to the full URL for the toplevel of |
| @@ -3095,7 +3095,7 @@ | ||
| 3095 | 3095 | cgi_reset_content(); |
| 3096 | 3096 | webpage_error("Case 7 from /test-warning"); |
| 3097 | 3097 | } |
| 3098 | 3098 | @ </ol> |
| 3099 | 3099 | @ <p>End of test</p> |
| 3100 | - style_footer(); | |
| 3100 | + style_finish_page("test"); | |
| 3101 | 3101 | } |
| 3102 | 3102 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1308,11 +1308,11 @@ | |
| 1308 | style_submenu_element("Stat", "stat"); |
| 1309 | fossil_version_blob(&versionInfo, verboseFlag); |
| 1310 | @ <pre> |
| 1311 | @ %h(blob_str(&versionInfo)) |
| 1312 | @ </pre> |
| 1313 | style_footer(); |
| 1314 | } |
| 1315 | |
| 1316 | |
| 1317 | /* |
| 1318 | ** Set the g.zBaseURL value to the full URL for the toplevel of |
| @@ -3095,7 +3095,7 @@ | |
| 3095 | cgi_reset_content(); |
| 3096 | webpage_error("Case 7 from /test-warning"); |
| 3097 | } |
| 3098 | @ </ol> |
| 3099 | @ <p>End of test</p> |
| 3100 | style_footer(); |
| 3101 | } |
| 3102 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1308,11 +1308,11 @@ | |
| 1308 | style_submenu_element("Stat", "stat"); |
| 1309 | fossil_version_blob(&versionInfo, verboseFlag); |
| 1310 | @ <pre> |
| 1311 | @ %h(blob_str(&versionInfo)) |
| 1312 | @ </pre> |
| 1313 | style_finish_page("version"); |
| 1314 | } |
| 1315 | |
| 1316 | |
| 1317 | /* |
| 1318 | ** Set the g.zBaseURL value to the full URL for the toplevel of |
| @@ -3095,7 +3095,7 @@ | |
| 3095 | cgi_reset_content(); |
| 3096 | webpage_error("Case 7 from /test-warning"); |
| 3097 | } |
| 3098 | @ </ol> |
| 3099 | @ <p>End of test</p> |
| 3100 | style_finish_page("test"); |
| 3101 | } |
| 3102 |
+1
-1
| --- src/moderate.c | ||
| +++ src/moderate.c | ||
| @@ -189,11 +189,11 @@ | ||
| 189 | 189 | ); |
| 190 | 190 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 191 | 191 | www_print_timeline(&q, 0, 0, 0, 0, 0, 0, 0); |
| 192 | 192 | db_finalize(&q); |
| 193 | 193 | } |
| 194 | - style_footer(); | |
| 194 | + style_finish_page("modreq"); | |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | /* |
| 198 | 198 | ** Disapproves any entries in the modreq table which belong to any |
| 199 | 199 | ** user whose name is no longer found in the user table. This is only |
| 200 | 200 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -189,11 +189,11 @@ | |
| 189 | ); |
| 190 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 191 | www_print_timeline(&q, 0, 0, 0, 0, 0, 0, 0); |
| 192 | db_finalize(&q); |
| 193 | } |
| 194 | style_footer(); |
| 195 | } |
| 196 | |
| 197 | /* |
| 198 | ** Disapproves any entries in the modreq table which belong to any |
| 199 | ** user whose name is no longer found in the user table. This is only |
| 200 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -189,11 +189,11 @@ | |
| 189 | ); |
| 190 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 191 | www_print_timeline(&q, 0, 0, 0, 0, 0, 0, 0); |
| 192 | db_finalize(&q); |
| 193 | } |
| 194 | style_finish_page("modreq"); |
| 195 | } |
| 196 | |
| 197 | /* |
| 198 | ** Disapproves any entries in the modreq table which belong to any |
| 199 | ** user whose name is no longer found in the user table. This is only |
| 200 |
+6
-6
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -668,11 +668,11 @@ | ||
| 668 | 668 | @ </li></ul> |
| 669 | 669 | @ </p></li> |
| 670 | 670 | } |
| 671 | 671 | @ </ol> |
| 672 | 672 | db_finalize(&q); |
| 673 | - style_footer(); | |
| 673 | + style_finish_page("ambiguous"); | |
| 674 | 674 | } |
| 675 | 675 | |
| 676 | 676 | /* |
| 677 | 677 | ** Convert the name in CGI parameter zParamName into a rid and return that |
| 678 | 678 | ** rid. If the CGI parameter is missing or is not a valid artifact tag, |
| @@ -1328,11 +1328,11 @@ | ||
| 1328 | 1328 | for(i=1; i<=mx; i+=n){ |
| 1329 | 1329 | @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) |
| 1330 | 1330 | @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> |
| 1331 | 1331 | } |
| 1332 | 1332 | @ </ul> |
| 1333 | - style_footer(); | |
| 1333 | + style_finish_page("bloblist"); | |
| 1334 | 1334 | return; |
| 1335 | 1335 | } |
| 1336 | 1336 | if( phantomOnly || privOnly || mx>n ){ |
| 1337 | 1337 | style_submenu_element("Index", "bloblist"); |
| 1338 | 1338 | } |
| @@ -1407,11 +1407,11 @@ | ||
| 1407 | 1407 | } |
| 1408 | 1408 | @ </tr> |
| 1409 | 1409 | } |
| 1410 | 1410 | @ </table> |
| 1411 | 1411 | db_finalize(&q); |
| 1412 | - style_footer(); | |
| 1412 | + style_finish_page("bloblist"); | |
| 1413 | 1413 | } |
| 1414 | 1414 | |
| 1415 | 1415 | /* |
| 1416 | 1416 | ** Output HTML that shows a table of all public phantoms. |
| 1417 | 1417 | */ |
| @@ -1477,11 +1477,11 @@ | ||
| 1477 | 1477 | } |
| 1478 | 1478 | if( g.perm.Write ){ |
| 1479 | 1479 | style_submenu_element("Artifact Stats", "artifact_stats"); |
| 1480 | 1480 | } |
| 1481 | 1481 | table_of_public_phantoms(); |
| 1482 | - style_footer(); | |
| 1482 | + style_finish_page("phantoms"); | |
| 1483 | 1483 | } |
| 1484 | 1484 | |
| 1485 | 1485 | /* |
| 1486 | 1486 | ** WEBPAGE: bigbloblist |
| 1487 | 1487 | ** |
| @@ -1541,11 +1541,11 @@ | ||
| 1541 | 1541 | @ </tr> |
| 1542 | 1542 | } |
| 1543 | 1543 | @ </tbody></table> |
| 1544 | 1544 | db_finalize(&q); |
| 1545 | 1545 | style_table_sorter(); |
| 1546 | - style_footer(); | |
| 1546 | + style_finish_page("bigbloblist"); | |
| 1547 | 1547 | } |
| 1548 | 1548 | |
| 1549 | 1549 | /* |
| 1550 | 1550 | ** COMMAND: test-unsent |
| 1551 | 1551 | ** |
| @@ -1665,7 +1665,7 @@ | ||
| 1665 | 1665 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1666 | 1666 | " FROM event WHERE event.type='ci'" |
| 1667 | 1667 | " ORDER BY 1"); |
| 1668 | 1668 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1669 | 1669 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1670 | - style_footer(); | |
| 1670 | + style_finish_page("hash-collisions"); | |
| 1671 | 1671 | } |
| 1672 | 1672 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -668,11 +668,11 @@ | |
| 668 | @ </li></ul> |
| 669 | @ </p></li> |
| 670 | } |
| 671 | @ </ol> |
| 672 | db_finalize(&q); |
| 673 | style_footer(); |
| 674 | } |
| 675 | |
| 676 | /* |
| 677 | ** Convert the name in CGI parameter zParamName into a rid and return that |
| 678 | ** rid. If the CGI parameter is missing or is not a valid artifact tag, |
| @@ -1328,11 +1328,11 @@ | |
| 1328 | for(i=1; i<=mx; i+=n){ |
| 1329 | @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) |
| 1330 | @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> |
| 1331 | } |
| 1332 | @ </ul> |
| 1333 | style_footer(); |
| 1334 | return; |
| 1335 | } |
| 1336 | if( phantomOnly || privOnly || mx>n ){ |
| 1337 | style_submenu_element("Index", "bloblist"); |
| 1338 | } |
| @@ -1407,11 +1407,11 @@ | |
| 1407 | } |
| 1408 | @ </tr> |
| 1409 | } |
| 1410 | @ </table> |
| 1411 | db_finalize(&q); |
| 1412 | style_footer(); |
| 1413 | } |
| 1414 | |
| 1415 | /* |
| 1416 | ** Output HTML that shows a table of all public phantoms. |
| 1417 | */ |
| @@ -1477,11 +1477,11 @@ | |
| 1477 | } |
| 1478 | if( g.perm.Write ){ |
| 1479 | style_submenu_element("Artifact Stats", "artifact_stats"); |
| 1480 | } |
| 1481 | table_of_public_phantoms(); |
| 1482 | style_footer(); |
| 1483 | } |
| 1484 | |
| 1485 | /* |
| 1486 | ** WEBPAGE: bigbloblist |
| 1487 | ** |
| @@ -1541,11 +1541,11 @@ | |
| 1541 | @ </tr> |
| 1542 | } |
| 1543 | @ </tbody></table> |
| 1544 | db_finalize(&q); |
| 1545 | style_table_sorter(); |
| 1546 | style_footer(); |
| 1547 | } |
| 1548 | |
| 1549 | /* |
| 1550 | ** COMMAND: test-unsent |
| 1551 | ** |
| @@ -1665,7 +1665,7 @@ | |
| 1665 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1666 | " FROM event WHERE event.type='ci'" |
| 1667 | " ORDER BY 1"); |
| 1668 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1669 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1670 | style_footer(); |
| 1671 | } |
| 1672 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -668,11 +668,11 @@ | |
| 668 | @ </li></ul> |
| 669 | @ </p></li> |
| 670 | } |
| 671 | @ </ol> |
| 672 | db_finalize(&q); |
| 673 | style_finish_page("ambiguous"); |
| 674 | } |
| 675 | |
| 676 | /* |
| 677 | ** Convert the name in CGI parameter zParamName into a rid and return that |
| 678 | ** rid. If the CGI parameter is missing or is not a valid artifact tag, |
| @@ -1328,11 +1328,11 @@ | |
| 1328 | for(i=1; i<=mx; i+=n){ |
| 1329 | @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) |
| 1330 | @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> |
| 1331 | } |
| 1332 | @ </ul> |
| 1333 | style_finish_page("bloblist"); |
| 1334 | return; |
| 1335 | } |
| 1336 | if( phantomOnly || privOnly || mx>n ){ |
| 1337 | style_submenu_element("Index", "bloblist"); |
| 1338 | } |
| @@ -1407,11 +1407,11 @@ | |
| 1407 | } |
| 1408 | @ </tr> |
| 1409 | } |
| 1410 | @ </table> |
| 1411 | db_finalize(&q); |
| 1412 | style_finish_page("bloblist"); |
| 1413 | } |
| 1414 | |
| 1415 | /* |
| 1416 | ** Output HTML that shows a table of all public phantoms. |
| 1417 | */ |
| @@ -1477,11 +1477,11 @@ | |
| 1477 | } |
| 1478 | if( g.perm.Write ){ |
| 1479 | style_submenu_element("Artifact Stats", "artifact_stats"); |
| 1480 | } |
| 1481 | table_of_public_phantoms(); |
| 1482 | style_finish_page("phantoms"); |
| 1483 | } |
| 1484 | |
| 1485 | /* |
| 1486 | ** WEBPAGE: bigbloblist |
| 1487 | ** |
| @@ -1541,11 +1541,11 @@ | |
| 1541 | @ </tr> |
| 1542 | } |
| 1543 | @ </tbody></table> |
| 1544 | db_finalize(&q); |
| 1545 | style_table_sorter(); |
| 1546 | style_finish_page("bigbloblist"); |
| 1547 | } |
| 1548 | |
| 1549 | /* |
| 1550 | ** COMMAND: test-unsent |
| 1551 | ** |
| @@ -1665,7 +1665,7 @@ | |
| 1665 | collision_report("SELECT (SELECT uuid FROM blob WHERE rid=objid)" |
| 1666 | " FROM event WHERE event.type='ci'" |
| 1667 | " ORDER BY 1"); |
| 1668 | @ <h1>Hash Prefix Collisions on All Artifacts</h1> |
| 1669 | collision_report("SELECT uuid FROM blob ORDER BY 1"); |
| 1670 | style_finish_page("hash-collisions"); |
| 1671 | } |
| 1672 |
+1
-1
| --- src/path.c | ||
| +++ src/path.c | ||
| @@ -651,7 +651,7 @@ | ||
| 651 | 651 | @ <td>%z(href("%R/info/%!S",zUuid))%S(zUuid)</a></td></tr> |
| 652 | 652 | } |
| 653 | 653 | @ </tbody></table> |
| 654 | 654 | db_finalize(&q); |
| 655 | 655 | style_table_sorter(); |
| 656 | - style_footer(); | |
| 656 | + style_finish_page("test"); | |
| 657 | 657 | } |
| 658 | 658 |
| --- src/path.c | |
| +++ src/path.c | |
| @@ -651,7 +651,7 @@ | |
| 651 | @ <td>%z(href("%R/info/%!S",zUuid))%S(zUuid)</a></td></tr> |
| 652 | } |
| 653 | @ </tbody></table> |
| 654 | db_finalize(&q); |
| 655 | style_table_sorter(); |
| 656 | style_footer(); |
| 657 | } |
| 658 |
| --- src/path.c | |
| +++ src/path.c | |
| @@ -651,7 +651,7 @@ | |
| 651 | @ <td>%z(href("%R/info/%!S",zUuid))%S(zUuid)</a></td></tr> |
| 652 | } |
| 653 | @ </tbody></table> |
| 654 | db_finalize(&q); |
| 655 | style_table_sorter(); |
| 656 | style_finish_page("test"); |
| 657 | } |
| 658 |
+1
-1
| --- src/piechart.c | ||
| +++ src/piechart.c | ||
| @@ -328,7 +328,7 @@ | ||
| 328 | 328 | @ <li> <a href='test-piechart?data=2,2,2,2,2,44,44,2,2,2,2,2'>Case 2</a> |
| 329 | 329 | @ <li> <a href='test-piechart?data=20,2,2,2,2,2,2,2,2,2,2,80'>Case 3</a> |
| 330 | 330 | @ <li> <a href='test-piechart?data=80,2,2,2,2,2,2,2,2,2,2,20'>Case 4</a> |
| 331 | 331 | @ <li> <a href='test-piechart?data=2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2'>Case 5</a> |
| 332 | 332 | @ </ul> |
| 333 | - style_footer(); | |
| 333 | + style_finish_page("test"); | |
| 334 | 334 | } |
| 335 | 335 |
| --- src/piechart.c | |
| +++ src/piechart.c | |
| @@ -328,7 +328,7 @@ | |
| 328 | @ <li> <a href='test-piechart?data=2,2,2,2,2,44,44,2,2,2,2,2'>Case 2</a> |
| 329 | @ <li> <a href='test-piechart?data=20,2,2,2,2,2,2,2,2,2,2,80'>Case 3</a> |
| 330 | @ <li> <a href='test-piechart?data=80,2,2,2,2,2,2,2,2,2,2,20'>Case 4</a> |
| 331 | @ <li> <a href='test-piechart?data=2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2'>Case 5</a> |
| 332 | @ </ul> |
| 333 | style_footer(); |
| 334 | } |
| 335 |
| --- src/piechart.c | |
| +++ src/piechart.c | |
| @@ -328,7 +328,7 @@ | |
| 328 | @ <li> <a href='test-piechart?data=2,2,2,2,2,44,44,2,2,2,2,2'>Case 2</a> |
| 329 | @ <li> <a href='test-piechart?data=20,2,2,2,2,2,2,2,2,2,2,80'>Case 3</a> |
| 330 | @ <li> <a href='test-piechart?data=80,2,2,2,2,2,2,2,2,2,2,20'>Case 4</a> |
| 331 | @ <li> <a href='test-piechart?data=2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2'>Case 5</a> |
| 332 | @ </ul> |
| 333 | style_finish_page("test"); |
| 334 | } |
| 335 |
+1
-1
| --- src/pikchrshow.c | ||
| +++ src/pikchrshow.c | ||
| @@ -373,11 +373,11 @@ | ||
| 373 | 373 | } CX("</div>"/*sbs-wrapper*/); |
| 374 | 374 | builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget", |
| 375 | 375 | "storage", "pikchr", 0); |
| 376 | 376 | builtin_request_js("fossil.page.pikchrshow.js"); |
| 377 | 377 | builtin_fulfill_js_requests(); |
| 378 | - style_footer(); | |
| 378 | + style_finish_page("pikchrshow"); | |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | 381 | /* |
| 382 | 382 | ** COMMAND: pikchr* |
| 383 | 383 | ** |
| 384 | 384 |
| --- src/pikchrshow.c | |
| +++ src/pikchrshow.c | |
| @@ -373,11 +373,11 @@ | |
| 373 | } CX("</div>"/*sbs-wrapper*/); |
| 374 | builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget", |
| 375 | "storage", "pikchr", 0); |
| 376 | builtin_request_js("fossil.page.pikchrshow.js"); |
| 377 | builtin_fulfill_js_requests(); |
| 378 | style_footer(); |
| 379 | } |
| 380 | |
| 381 | /* |
| 382 | ** COMMAND: pikchr* |
| 383 | ** |
| 384 |
| --- src/pikchrshow.c | |
| +++ src/pikchrshow.c | |
| @@ -373,11 +373,11 @@ | |
| 373 | } CX("</div>"/*sbs-wrapper*/); |
| 374 | builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget", |
| 375 | "storage", "pikchr", 0); |
| 376 | builtin_request_js("fossil.page.pikchrshow.js"); |
| 377 | builtin_fulfill_js_requests(); |
| 378 | style_finish_page("pikchrshow"); |
| 379 | } |
| 380 | |
| 381 | /* |
| 382 | ** COMMAND: pikchr* |
| 383 | ** |
| 384 |
+1
-1
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -1101,11 +1101,11 @@ | ||
| 1101 | 1101 | cgi_set_content_type("text/html"); |
| 1102 | 1102 | style_header("Bad Request"); |
| 1103 | 1103 | etag_cancel(); |
| 1104 | 1104 | @ <p class="generalError">%h(z)</p> |
| 1105 | 1105 | cgi_set_status(400, "Bad Request"); |
| 1106 | - style_footer(); | |
| 1106 | + style_finish_page("error"); | |
| 1107 | 1107 | cgi_reply(); |
| 1108 | 1108 | }else if( !g.fQuiet ){ |
| 1109 | 1109 | fossil_force_newline(); |
| 1110 | 1110 | fossil_trace("%s\n", z); |
| 1111 | 1111 | } |
| 1112 | 1112 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -1101,11 +1101,11 @@ | |
| 1101 | cgi_set_content_type("text/html"); |
| 1102 | style_header("Bad Request"); |
| 1103 | etag_cancel(); |
| 1104 | @ <p class="generalError">%h(z)</p> |
| 1105 | cgi_set_status(400, "Bad Request"); |
| 1106 | style_footer(); |
| 1107 | cgi_reply(); |
| 1108 | }else if( !g.fQuiet ){ |
| 1109 | fossil_force_newline(); |
| 1110 | fossil_trace("%s\n", z); |
| 1111 | } |
| 1112 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -1101,11 +1101,11 @@ | |
| 1101 | cgi_set_content_type("text/html"); |
| 1102 | style_header("Bad Request"); |
| 1103 | etag_cancel(); |
| 1104 | @ <p class="generalError">%h(z)</p> |
| 1105 | cgi_set_status(400, "Bad Request"); |
| 1106 | style_finish_page("error"); |
| 1107 | cgi_reply(); |
| 1108 | }else if( !g.fQuiet ){ |
| 1109 | fossil_force_newline(); |
| 1110 | fossil_trace("%s\n", z); |
| 1111 | } |
| 1112 |
+1
-1
| --- src/repolist.c | ||
| +++ src/repolist.c | ||
| @@ -248,11 +248,11 @@ | ||
| 248 | 248 | ** for display. */ |
| 249 | 249 | login_check_credentials(); |
| 250 | 250 | style_header("Repository List"); |
| 251 | 251 | @ %s(blob_str(&html)) |
| 252 | 252 | style_table_sorter(); |
| 253 | - style_footer(); | |
| 253 | + style_finish_page("repolist"); | |
| 254 | 254 | }else{ |
| 255 | 255 | /* If no repositories were found that had the "repolist_skin" |
| 256 | 256 | ** property set, then use a default skin */ |
| 257 | 257 | @ <html> |
| 258 | 258 | @ <head> |
| 259 | 259 |
| --- src/repolist.c | |
| +++ src/repolist.c | |
| @@ -248,11 +248,11 @@ | |
| 248 | ** for display. */ |
| 249 | login_check_credentials(); |
| 250 | style_header("Repository List"); |
| 251 | @ %s(blob_str(&html)) |
| 252 | style_table_sorter(); |
| 253 | style_footer(); |
| 254 | }else{ |
| 255 | /* If no repositories were found that had the "repolist_skin" |
| 256 | ** property set, then use a default skin */ |
| 257 | @ <html> |
| 258 | @ <head> |
| 259 |
| --- src/repolist.c | |
| +++ src/repolist.c | |
| @@ -248,11 +248,11 @@ | |
| 248 | ** for display. */ |
| 249 | login_check_credentials(); |
| 250 | style_header("Repository List"); |
| 251 | @ %s(blob_str(&html)) |
| 252 | style_table_sorter(); |
| 253 | style_finish_page("repolist"); |
| 254 | }else{ |
| 255 | /* If no repositories were found that had the "repolist_skin" |
| 256 | ** property set, then use a default skin */ |
| 257 | @ <html> |
| 258 | @ <head> |
| 259 |
+7
-7
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -97,11 +97,11 @@ | ||
| 97 | 97 | Th_Render(zScript); |
| 98 | 98 | |
| 99 | 99 | blob_reset(&ril); |
| 100 | 100 | if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1); |
| 101 | 101 | |
| 102 | - style_footer(); | |
| 102 | + style_finish_page("reportlist"); | |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | 105 | /* |
| 106 | 106 | ** Remove whitespace from both ends of a string. |
| 107 | 107 | */ |
| @@ -319,11 +319,11 @@ | ||
| 319 | 319 | db_prepare(&q, "SELECT title, sqlcode, owner, cols " |
| 320 | 320 | "FROM reportfmt WHERE rn=%d",rn); |
| 321 | 321 | style_header("SQL For Report Format Number %d", rn); |
| 322 | 322 | if( db_step(&q)!=SQLITE_ROW ){ |
| 323 | 323 | @ <p>Unknown report number: %d(rn)</p> |
| 324 | - style_footer(); | |
| 324 | + style_finish_page("report"); | |
| 325 | 325 | db_finalize(&q); |
| 326 | 326 | return; |
| 327 | 327 | } |
| 328 | 328 | zTitle = db_column_text(&q, 0); |
| 329 | 329 | zSQL = db_column_text(&q, 1); |
| @@ -341,11 +341,11 @@ | ||
| 341 | 341 | @ <td width=15></td><td valign="top"> |
| 342 | 342 | output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3"); |
| 343 | 343 | @ </td> |
| 344 | 344 | @ </tr></table> |
| 345 | 345 | report_format_hints(); |
| 346 | - style_footer(); | |
| 346 | + style_finish_page("report"); | |
| 347 | 347 | db_finalize(&q); |
| 348 | 348 | } |
| 349 | 349 | |
| 350 | 350 | /* |
| 351 | 351 | ** WEBPAGE: rptnew |
| @@ -401,11 +401,11 @@ | ||
| 401 | 401 | @ <input type="hidden" name="rn" value="%d(rn)"> |
| 402 | 402 | login_insert_csrf_secret(); |
| 403 | 403 | @ <input type="submit" name="del2" value="Delete The Report"> |
| 404 | 404 | @ <input type="submit" name="can" value="Cancel"> |
| 405 | 405 | @ </form> |
| 406 | - style_footer(); | |
| 406 | + style_finish_page("report"); | |
| 407 | 407 | return; |
| 408 | 408 | }else if( P("can") ){ |
| 409 | 409 | /* user cancelled */ |
| 410 | 410 | cgi_redirect("reportlist"); |
| 411 | 411 | return; |
| @@ -493,20 +493,20 @@ | ||
| 493 | 493 | if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){ |
| 494 | 494 | @ <p>This report format is owned by %h(zOwner). You are not allowed |
| 495 | 495 | @ to change it.</p> |
| 496 | 496 | @ </form> |
| 497 | 497 | report_format_hints(); |
| 498 | - style_footer(); | |
| 498 | + style_finish_page("report"); | |
| 499 | 499 | return; |
| 500 | 500 | } |
| 501 | 501 | @ <input type="submit" value="Apply Changes" /> |
| 502 | 502 | if( rn>0 ){ |
| 503 | 503 | @ <input type="submit" value="Delete This Report" name="del1" /> |
| 504 | 504 | } |
| 505 | 505 | @ </div></form> |
| 506 | 506 | report_format_hints(); |
| 507 | - style_footer(); | |
| 507 | + style_finish_page("report"); | |
| 508 | 508 | } |
| 509 | 509 | |
| 510 | 510 | /* |
| 511 | 511 | ** Output a bunch of text that provides information about report |
| 512 | 512 | ** formats |
| @@ -1048,11 +1048,11 @@ | ||
| 1048 | 1048 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1049 | 1049 | }else if( zErr2 ){ |
| 1050 | 1050 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1051 | 1051 | } |
| 1052 | 1052 | style_table_sorter(); |
| 1053 | - style_footer(); | |
| 1053 | + style_finish_page("report"); | |
| 1054 | 1054 | }else{ |
| 1055 | 1055 | report_restrict_sql(&zErr1); |
| 1056 | 1056 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1057 | 1057 | report_unrestrict_sql(); |
| 1058 | 1058 | cgi_set_content_type("text/plain"); |
| 1059 | 1059 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -97,11 +97,11 @@ | |
| 97 | Th_Render(zScript); |
| 98 | |
| 99 | blob_reset(&ril); |
| 100 | if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1); |
| 101 | |
| 102 | style_footer(); |
| 103 | } |
| 104 | |
| 105 | /* |
| 106 | ** Remove whitespace from both ends of a string. |
| 107 | */ |
| @@ -319,11 +319,11 @@ | |
| 319 | db_prepare(&q, "SELECT title, sqlcode, owner, cols " |
| 320 | "FROM reportfmt WHERE rn=%d",rn); |
| 321 | style_header("SQL For Report Format Number %d", rn); |
| 322 | if( db_step(&q)!=SQLITE_ROW ){ |
| 323 | @ <p>Unknown report number: %d(rn)</p> |
| 324 | style_footer(); |
| 325 | db_finalize(&q); |
| 326 | return; |
| 327 | } |
| 328 | zTitle = db_column_text(&q, 0); |
| 329 | zSQL = db_column_text(&q, 1); |
| @@ -341,11 +341,11 @@ | |
| 341 | @ <td width=15></td><td valign="top"> |
| 342 | output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3"); |
| 343 | @ </td> |
| 344 | @ </tr></table> |
| 345 | report_format_hints(); |
| 346 | style_footer(); |
| 347 | db_finalize(&q); |
| 348 | } |
| 349 | |
| 350 | /* |
| 351 | ** WEBPAGE: rptnew |
| @@ -401,11 +401,11 @@ | |
| 401 | @ <input type="hidden" name="rn" value="%d(rn)"> |
| 402 | login_insert_csrf_secret(); |
| 403 | @ <input type="submit" name="del2" value="Delete The Report"> |
| 404 | @ <input type="submit" name="can" value="Cancel"> |
| 405 | @ </form> |
| 406 | style_footer(); |
| 407 | return; |
| 408 | }else if( P("can") ){ |
| 409 | /* user cancelled */ |
| 410 | cgi_redirect("reportlist"); |
| 411 | return; |
| @@ -493,20 +493,20 @@ | |
| 493 | if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){ |
| 494 | @ <p>This report format is owned by %h(zOwner). You are not allowed |
| 495 | @ to change it.</p> |
| 496 | @ </form> |
| 497 | report_format_hints(); |
| 498 | style_footer(); |
| 499 | return; |
| 500 | } |
| 501 | @ <input type="submit" value="Apply Changes" /> |
| 502 | if( rn>0 ){ |
| 503 | @ <input type="submit" value="Delete This Report" name="del1" /> |
| 504 | } |
| 505 | @ </div></form> |
| 506 | report_format_hints(); |
| 507 | style_footer(); |
| 508 | } |
| 509 | |
| 510 | /* |
| 511 | ** Output a bunch of text that provides information about report |
| 512 | ** formats |
| @@ -1048,11 +1048,11 @@ | |
| 1048 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1049 | }else if( zErr2 ){ |
| 1050 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1051 | } |
| 1052 | style_table_sorter(); |
| 1053 | style_footer(); |
| 1054 | }else{ |
| 1055 | report_restrict_sql(&zErr1); |
| 1056 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1057 | report_unrestrict_sql(); |
| 1058 | cgi_set_content_type("text/plain"); |
| 1059 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -97,11 +97,11 @@ | |
| 97 | Th_Render(zScript); |
| 98 | |
| 99 | blob_reset(&ril); |
| 100 | if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1); |
| 101 | |
| 102 | style_finish_page("reportlist"); |
| 103 | } |
| 104 | |
| 105 | /* |
| 106 | ** Remove whitespace from both ends of a string. |
| 107 | */ |
| @@ -319,11 +319,11 @@ | |
| 319 | db_prepare(&q, "SELECT title, sqlcode, owner, cols " |
| 320 | "FROM reportfmt WHERE rn=%d",rn); |
| 321 | style_header("SQL For Report Format Number %d", rn); |
| 322 | if( db_step(&q)!=SQLITE_ROW ){ |
| 323 | @ <p>Unknown report number: %d(rn)</p> |
| 324 | style_finish_page("report"); |
| 325 | db_finalize(&q); |
| 326 | return; |
| 327 | } |
| 328 | zTitle = db_column_text(&q, 0); |
| 329 | zSQL = db_column_text(&q, 1); |
| @@ -341,11 +341,11 @@ | |
| 341 | @ <td width=15></td><td valign="top"> |
| 342 | output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3"); |
| 343 | @ </td> |
| 344 | @ </tr></table> |
| 345 | report_format_hints(); |
| 346 | style_finish_page("report"); |
| 347 | db_finalize(&q); |
| 348 | } |
| 349 | |
| 350 | /* |
| 351 | ** WEBPAGE: rptnew |
| @@ -401,11 +401,11 @@ | |
| 401 | @ <input type="hidden" name="rn" value="%d(rn)"> |
| 402 | login_insert_csrf_secret(); |
| 403 | @ <input type="submit" name="del2" value="Delete The Report"> |
| 404 | @ <input type="submit" name="can" value="Cancel"> |
| 405 | @ </form> |
| 406 | style_finish_page("report"); |
| 407 | return; |
| 408 | }else if( P("can") ){ |
| 409 | /* user cancelled */ |
| 410 | cgi_redirect("reportlist"); |
| 411 | return; |
| @@ -493,20 +493,20 @@ | |
| 493 | if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){ |
| 494 | @ <p>This report format is owned by %h(zOwner). You are not allowed |
| 495 | @ to change it.</p> |
| 496 | @ </form> |
| 497 | report_format_hints(); |
| 498 | style_finish_page("report"); |
| 499 | return; |
| 500 | } |
| 501 | @ <input type="submit" value="Apply Changes" /> |
| 502 | if( rn>0 ){ |
| 503 | @ <input type="submit" value="Delete This Report" name="del1" /> |
| 504 | } |
| 505 | @ </div></form> |
| 506 | report_format_hints(); |
| 507 | style_finish_page("report"); |
| 508 | } |
| 509 | |
| 510 | /* |
| 511 | ** Output a bunch of text that provides information about report |
| 512 | ** formats |
| @@ -1048,11 +1048,11 @@ | |
| 1048 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1049 | }else if( zErr2 ){ |
| 1050 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1051 | } |
| 1052 | style_table_sorter(); |
| 1053 | style_finish_page("report"); |
| 1054 | }else{ |
| 1055 | report_restrict_sql(&zErr1); |
| 1056 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1057 | report_unrestrict_sql(); |
| 1058 | cgi_set_content_type("text/plain"); |
| 1059 |
+5
-5
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -1212,11 +1212,11 @@ | ||
| 1212 | 1212 | */ |
| 1213 | 1213 | void search_page(void){ |
| 1214 | 1214 | login_check_credentials(); |
| 1215 | 1215 | style_header("Search"); |
| 1216 | 1216 | search_screen(SRCH_ALL, 1); |
| 1217 | - style_footer(); | |
| 1217 | + style_finish_page("search"); | |
| 1218 | 1218 | } |
| 1219 | 1219 | |
| 1220 | 1220 | |
| 1221 | 1221 | /* |
| 1222 | 1222 | ** This is a helper function for search_stext(). Writing into pOut |
| @@ -1981,11 +1981,11 @@ | ||
| 1981 | 1981 | int cnt1 = 0, cnt2 = 0, cnt3 = 0; |
| 1982 | 1982 | login_check_credentials(); |
| 1983 | 1983 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 1984 | 1984 | if( !search_index_exists() ){ |
| 1985 | 1985 | @ <p>Indexed search is disabled |
| 1986 | - style_footer(); | |
| 1986 | + style_finish_page("report"); | |
| 1987 | 1987 | return; |
| 1988 | 1988 | } |
| 1989 | 1989 | search_sql_setup(g.db); |
| 1990 | 1990 | style_submenu_element("Setup","%R/srchsetup"); |
| 1991 | 1991 | if( zId!=0 && (id = atoi(zId))>0 ){ |
| @@ -2025,11 +2025,11 @@ | ||
| 2025 | 2025 | style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zDocId[0]); |
| 2026 | 2026 | zName = mprintf("Unindexed '%c' docs",zDocId[0]); |
| 2027 | 2027 | style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zDocId[0]); |
| 2028 | 2028 | } |
| 2029 | 2029 | db_finalize(&q); |
| 2030 | - style_footer(); | |
| 2030 | + style_finish_page("test"); | |
| 2031 | 2031 | return; |
| 2032 | 2032 | } |
| 2033 | 2033 | if( zType!=0 && zType[0]!=0 && zType[1]==0 && |
| 2034 | 2034 | zIdxed!=0 && (zIdxed[0]=='1' || zIdxed[0]=='0') && zIdxed[1]==0 |
| 2035 | 2035 | ){ |
| @@ -2055,11 +2055,11 @@ | ||
| 2055 | 2055 | @ <li> <a href='test-ftsdocs?id=%d(db_column_int(&q,0))'> |
| 2056 | 2056 | @ %h(db_column_text(&q,1))</a> |
| 2057 | 2057 | } |
| 2058 | 2058 | @ </ul> |
| 2059 | 2059 | db_finalize(&q); |
| 2060 | - style_footer(); | |
| 2060 | + style_finish_page("test"); | |
| 2061 | 2061 | return; |
| 2062 | 2062 | } |
| 2063 | 2063 | style_header("Summary of ftsdocs"); |
| 2064 | 2064 | db_prepare(&q, |
| 2065 | 2065 | "SELECT type, sum(idxed IS TRUE), sum(idxed IS FALSE), count(*)" |
| @@ -2099,7 +2099,7 @@ | ||
| 2099 | 2099 | @ </tbody><tfooter> |
| 2100 | 2100 | @ <tr><th>Total<th align="right">%d(cnt1)<th align="right">%d(cnt2) |
| 2101 | 2101 | @ <th align="right">%d(cnt3) |
| 2102 | 2102 | @ </tfooter> |
| 2103 | 2103 | @ </table> |
| 2104 | - style_footer(); | |
| 2104 | + style_finish_page("test"); | |
| 2105 | 2105 | } |
| 2106 | 2106 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -1212,11 +1212,11 @@ | |
| 1212 | */ |
| 1213 | void search_page(void){ |
| 1214 | login_check_credentials(); |
| 1215 | style_header("Search"); |
| 1216 | search_screen(SRCH_ALL, 1); |
| 1217 | style_footer(); |
| 1218 | } |
| 1219 | |
| 1220 | |
| 1221 | /* |
| 1222 | ** This is a helper function for search_stext(). Writing into pOut |
| @@ -1981,11 +1981,11 @@ | |
| 1981 | int cnt1 = 0, cnt2 = 0, cnt3 = 0; |
| 1982 | login_check_credentials(); |
| 1983 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 1984 | if( !search_index_exists() ){ |
| 1985 | @ <p>Indexed search is disabled |
| 1986 | style_footer(); |
| 1987 | return; |
| 1988 | } |
| 1989 | search_sql_setup(g.db); |
| 1990 | style_submenu_element("Setup","%R/srchsetup"); |
| 1991 | if( zId!=0 && (id = atoi(zId))>0 ){ |
| @@ -2025,11 +2025,11 @@ | |
| 2025 | style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zDocId[0]); |
| 2026 | zName = mprintf("Unindexed '%c' docs",zDocId[0]); |
| 2027 | style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zDocId[0]); |
| 2028 | } |
| 2029 | db_finalize(&q); |
| 2030 | style_footer(); |
| 2031 | return; |
| 2032 | } |
| 2033 | if( zType!=0 && zType[0]!=0 && zType[1]==0 && |
| 2034 | zIdxed!=0 && (zIdxed[0]=='1' || zIdxed[0]=='0') && zIdxed[1]==0 |
| 2035 | ){ |
| @@ -2055,11 +2055,11 @@ | |
| 2055 | @ <li> <a href='test-ftsdocs?id=%d(db_column_int(&q,0))'> |
| 2056 | @ %h(db_column_text(&q,1))</a> |
| 2057 | } |
| 2058 | @ </ul> |
| 2059 | db_finalize(&q); |
| 2060 | style_footer(); |
| 2061 | return; |
| 2062 | } |
| 2063 | style_header("Summary of ftsdocs"); |
| 2064 | db_prepare(&q, |
| 2065 | "SELECT type, sum(idxed IS TRUE), sum(idxed IS FALSE), count(*)" |
| @@ -2099,7 +2099,7 @@ | |
| 2099 | @ </tbody><tfooter> |
| 2100 | @ <tr><th>Total<th align="right">%d(cnt1)<th align="right">%d(cnt2) |
| 2101 | @ <th align="right">%d(cnt3) |
| 2102 | @ </tfooter> |
| 2103 | @ </table> |
| 2104 | style_footer(); |
| 2105 | } |
| 2106 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -1212,11 +1212,11 @@ | |
| 1212 | */ |
| 1213 | void search_page(void){ |
| 1214 | login_check_credentials(); |
| 1215 | style_header("Search"); |
| 1216 | search_screen(SRCH_ALL, 1); |
| 1217 | style_finish_page("search"); |
| 1218 | } |
| 1219 | |
| 1220 | |
| 1221 | /* |
| 1222 | ** This is a helper function for search_stext(). Writing into pOut |
| @@ -1981,11 +1981,11 @@ | |
| 1981 | int cnt1 = 0, cnt2 = 0, cnt3 = 0; |
| 1982 | login_check_credentials(); |
| 1983 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 1984 | if( !search_index_exists() ){ |
| 1985 | @ <p>Indexed search is disabled |
| 1986 | style_finish_page("report"); |
| 1987 | return; |
| 1988 | } |
| 1989 | search_sql_setup(g.db); |
| 1990 | style_submenu_element("Setup","%R/srchsetup"); |
| 1991 | if( zId!=0 && (id = atoi(zId))>0 ){ |
| @@ -2025,11 +2025,11 @@ | |
| 2025 | style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zDocId[0]); |
| 2026 | zName = mprintf("Unindexed '%c' docs",zDocId[0]); |
| 2027 | style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zDocId[0]); |
| 2028 | } |
| 2029 | db_finalize(&q); |
| 2030 | style_finish_page("test"); |
| 2031 | return; |
| 2032 | } |
| 2033 | if( zType!=0 && zType[0]!=0 && zType[1]==0 && |
| 2034 | zIdxed!=0 && (zIdxed[0]=='1' || zIdxed[0]=='0') && zIdxed[1]==0 |
| 2035 | ){ |
| @@ -2055,11 +2055,11 @@ | |
| 2055 | @ <li> <a href='test-ftsdocs?id=%d(db_column_int(&q,0))'> |
| 2056 | @ %h(db_column_text(&q,1))</a> |
| 2057 | } |
| 2058 | @ </ul> |
| 2059 | db_finalize(&q); |
| 2060 | style_finish_page("test"); |
| 2061 | return; |
| 2062 | } |
| 2063 | style_header("Summary of ftsdocs"); |
| 2064 | db_prepare(&q, |
| 2065 | "SELECT type, sum(idxed IS TRUE), sum(idxed IS FALSE), count(*)" |
| @@ -2099,7 +2099,7 @@ | |
| 2099 | @ </tbody><tfooter> |
| 2100 | @ <tr><th>Total<th align="right">%d(cnt1)<th align="right">%d(cnt2) |
| 2101 | @ <th align="right">%d(cnt3) |
| 2102 | @ </tfooter> |
| 2103 | @ </table> |
| 2104 | style_finish_page("test"); |
| 2105 | } |
| 2106 |
+6
-6
| --- src/security_audit.c | ||
| +++ src/security_audit.c | ||
| @@ -585,11 +585,11 @@ | ||
| 585 | 585 | table_of_public_phantoms(); |
| 586 | 586 | @ </li> |
| 587 | 587 | } |
| 588 | 588 | |
| 589 | 589 | @ </ol> |
| 590 | - style_footer(); | |
| 590 | + style_finish_page("secaudit"); | |
| 591 | 591 | } |
| 592 | 592 | |
| 593 | 593 | /* |
| 594 | 594 | ** WEBPAGE: takeitprivate |
| 595 | 595 | ** |
| @@ -627,11 +627,11 @@ | ||
| 627 | 627 | @ <form action="%s(g.zPath)" method="post"> |
| 628 | 628 | @ <input type="submit" name="apply" value="Make It Private"> |
| 629 | 629 | @ <input type="submit" name="cancel" value="Cancel"> |
| 630 | 630 | @ </form> |
| 631 | 631 | |
| 632 | - style_footer(); | |
| 632 | + style_finish_page("takeitprivate"); | |
| 633 | 633 | } |
| 634 | 634 | |
| 635 | 635 | /* |
| 636 | 636 | ** The maximum number of bytes of log to show |
| 637 | 637 | */ |
| @@ -668,11 +668,11 @@ | ||
| 668 | 668 | @ If the server is running using one of |
| 669 | 669 | @ the "fossil http" or "fossil server" commands then add |
| 670 | 670 | @ a command-line option "--errorlog <i>FILENAME</i>" to that |
| 671 | 671 | @ command. |
| 672 | 672 | @ </ol> |
| 673 | - style_footer(); | |
| 673 | + style_finish_page("errorlog"); | |
| 674 | 674 | return; |
| 675 | 675 | } |
| 676 | 676 | if( P("truncate1") && cgi_csrf_safe(1) ){ |
| 677 | 677 | fclose(fopen(g.zErrlog,"w")); |
| 678 | 678 | } |
| @@ -688,20 +688,20 @@ | ||
| 688 | 688 | @ <form action="%R/errorlog" method="POST"> |
| 689 | 689 | @ <p>Confirm that you want to truncate the %,lld(szFile)-byte error log: |
| 690 | 690 | @ <input type="submit" name="truncate1" value="Confirm"> |
| 691 | 691 | @ <input type="submit" name="cancel" value="Cancel"> |
| 692 | 692 | @ </form> |
| 693 | - style_footer(); | |
| 693 | + style_finish_page("errorlog"); | |
| 694 | 694 | return; |
| 695 | 695 | } |
| 696 | 696 | @ <p>The server error log at "%h(g.zErrlog)" is %,lld(szFile) bytes in size. |
| 697 | 697 | style_submenu_element("Download", "%R/errorlog?download"); |
| 698 | 698 | style_submenu_element("Truncate", "%R/errorlog?truncate"); |
| 699 | 699 | in = fossil_fopen(g.zErrlog, "rb"); |
| 700 | 700 | if( in==0 ){ |
| 701 | 701 | @ <p class='generalError'>Unable to open that file for reading!</p> |
| 702 | - style_footer(); | |
| 702 | + style_finish_page("errorlog"); | |
| 703 | 703 | return; |
| 704 | 704 | } |
| 705 | 705 | if( szFile>MXSHOWLOG && P("all")==0 ){ |
| 706 | 706 | @ <form action="%R/errorlog" method="POST"> |
| 707 | 707 | @ <p>Only the last %,d(MXSHOWLOG) bytes are shown. |
| @@ -714,7 +714,7 @@ | ||
| 714 | 714 | while( fgets(z, sizeof(z), in) ){ |
| 715 | 715 | @ %h(z)\ |
| 716 | 716 | } |
| 717 | 717 | fclose(in); |
| 718 | 718 | @ </pre> |
| 719 | - style_footer(); | |
| 719 | + style_finish_page("errorlog"); | |
| 720 | 720 | } |
| 721 | 721 |
| --- src/security_audit.c | |
| +++ src/security_audit.c | |
| @@ -585,11 +585,11 @@ | |
| 585 | table_of_public_phantoms(); |
| 586 | @ </li> |
| 587 | } |
| 588 | |
| 589 | @ </ol> |
| 590 | style_footer(); |
| 591 | } |
| 592 | |
| 593 | /* |
| 594 | ** WEBPAGE: takeitprivate |
| 595 | ** |
| @@ -627,11 +627,11 @@ | |
| 627 | @ <form action="%s(g.zPath)" method="post"> |
| 628 | @ <input type="submit" name="apply" value="Make It Private"> |
| 629 | @ <input type="submit" name="cancel" value="Cancel"> |
| 630 | @ </form> |
| 631 | |
| 632 | style_footer(); |
| 633 | } |
| 634 | |
| 635 | /* |
| 636 | ** The maximum number of bytes of log to show |
| 637 | */ |
| @@ -668,11 +668,11 @@ | |
| 668 | @ If the server is running using one of |
| 669 | @ the "fossil http" or "fossil server" commands then add |
| 670 | @ a command-line option "--errorlog <i>FILENAME</i>" to that |
| 671 | @ command. |
| 672 | @ </ol> |
| 673 | style_footer(); |
| 674 | return; |
| 675 | } |
| 676 | if( P("truncate1") && cgi_csrf_safe(1) ){ |
| 677 | fclose(fopen(g.zErrlog,"w")); |
| 678 | } |
| @@ -688,20 +688,20 @@ | |
| 688 | @ <form action="%R/errorlog" method="POST"> |
| 689 | @ <p>Confirm that you want to truncate the %,lld(szFile)-byte error log: |
| 690 | @ <input type="submit" name="truncate1" value="Confirm"> |
| 691 | @ <input type="submit" name="cancel" value="Cancel"> |
| 692 | @ </form> |
| 693 | style_footer(); |
| 694 | return; |
| 695 | } |
| 696 | @ <p>The server error log at "%h(g.zErrlog)" is %,lld(szFile) bytes in size. |
| 697 | style_submenu_element("Download", "%R/errorlog?download"); |
| 698 | style_submenu_element("Truncate", "%R/errorlog?truncate"); |
| 699 | in = fossil_fopen(g.zErrlog, "rb"); |
| 700 | if( in==0 ){ |
| 701 | @ <p class='generalError'>Unable to open that file for reading!</p> |
| 702 | style_footer(); |
| 703 | return; |
| 704 | } |
| 705 | if( szFile>MXSHOWLOG && P("all")==0 ){ |
| 706 | @ <form action="%R/errorlog" method="POST"> |
| 707 | @ <p>Only the last %,d(MXSHOWLOG) bytes are shown. |
| @@ -714,7 +714,7 @@ | |
| 714 | while( fgets(z, sizeof(z), in) ){ |
| 715 | @ %h(z)\ |
| 716 | } |
| 717 | fclose(in); |
| 718 | @ </pre> |
| 719 | style_footer(); |
| 720 | } |
| 721 |
| --- src/security_audit.c | |
| +++ src/security_audit.c | |
| @@ -585,11 +585,11 @@ | |
| 585 | table_of_public_phantoms(); |
| 586 | @ </li> |
| 587 | } |
| 588 | |
| 589 | @ </ol> |
| 590 | style_finish_page("secaudit"); |
| 591 | } |
| 592 | |
| 593 | /* |
| 594 | ** WEBPAGE: takeitprivate |
| 595 | ** |
| @@ -627,11 +627,11 @@ | |
| 627 | @ <form action="%s(g.zPath)" method="post"> |
| 628 | @ <input type="submit" name="apply" value="Make It Private"> |
| 629 | @ <input type="submit" name="cancel" value="Cancel"> |
| 630 | @ </form> |
| 631 | |
| 632 | style_finish_page("takeitprivate"); |
| 633 | } |
| 634 | |
| 635 | /* |
| 636 | ** The maximum number of bytes of log to show |
| 637 | */ |
| @@ -668,11 +668,11 @@ | |
| 668 | @ If the server is running using one of |
| 669 | @ the "fossil http" or "fossil server" commands then add |
| 670 | @ a command-line option "--errorlog <i>FILENAME</i>" to that |
| 671 | @ command. |
| 672 | @ </ol> |
| 673 | style_finish_page("errorlog"); |
| 674 | return; |
| 675 | } |
| 676 | if( P("truncate1") && cgi_csrf_safe(1) ){ |
| 677 | fclose(fopen(g.zErrlog,"w")); |
| 678 | } |
| @@ -688,20 +688,20 @@ | |
| 688 | @ <form action="%R/errorlog" method="POST"> |
| 689 | @ <p>Confirm that you want to truncate the %,lld(szFile)-byte error log: |
| 690 | @ <input type="submit" name="truncate1" value="Confirm"> |
| 691 | @ <input type="submit" name="cancel" value="Cancel"> |
| 692 | @ </form> |
| 693 | style_finish_page("errorlog"); |
| 694 | return; |
| 695 | } |
| 696 | @ <p>The server error log at "%h(g.zErrlog)" is %,lld(szFile) bytes in size. |
| 697 | style_submenu_element("Download", "%R/errorlog?download"); |
| 698 | style_submenu_element("Truncate", "%R/errorlog?truncate"); |
| 699 | in = fossil_fopen(g.zErrlog, "rb"); |
| 700 | if( in==0 ){ |
| 701 | @ <p class='generalError'>Unable to open that file for reading!</p> |
| 702 | style_finish_page("errorlog"); |
| 703 | return; |
| 704 | } |
| 705 | if( szFile>MXSHOWLOG && P("all")==0 ){ |
| 706 | @ <form action="%R/errorlog" method="POST"> |
| 707 | @ <p>Only the last %,d(MXSHOWLOG) bytes are shown. |
| @@ -714,7 +714,7 @@ | |
| 714 | while( fgets(z, sizeof(z), in) ){ |
| 715 | @ %h(z)\ |
| 716 | } |
| 717 | fclose(in); |
| 718 | @ </pre> |
| 719 | style_finish_page("errorlog"); |
| 720 | } |
| 721 |
+15
-15
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -175,11 +175,11 @@ | ||
| 175 | 175 | setup_menu_entry("TH1", "admin_th1", |
| 176 | 176 | "Enter raw TH1 commands"); |
| 177 | 177 | } |
| 178 | 178 | @ </table> |
| 179 | 179 | |
| 180 | - style_footer(); | |
| 180 | + style_finish_page("setup"); | |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | 183 | /* |
| 184 | 184 | ** Generate a checkbox for an attribute. |
| 185 | 185 | */ |
| @@ -576,11 +576,11 @@ | ||
| 576 | 576 | |
| 577 | 577 | @ <hr /> |
| 578 | 578 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 579 | 579 | @ </div></form> |
| 580 | 580 | db_end_transaction(0); |
| 581 | - style_footer(); | |
| 581 | + style_finish_page("setup"); | |
| 582 | 582 | } |
| 583 | 583 | |
| 584 | 584 | /* |
| 585 | 585 | ** WEBPAGE: setup_login_group |
| 586 | 586 | ** |
| @@ -704,11 +704,11 @@ | ||
| 704 | 704 | } |
| 705 | 705 | db_finalize(&q); |
| 706 | 706 | @ </tbody></table> |
| 707 | 707 | style_table_sorter(); |
| 708 | 708 | } |
| 709 | - style_footer(); | |
| 709 | + style_finish_page("setup"); | |
| 710 | 710 | } |
| 711 | 711 | |
| 712 | 712 | /* |
| 713 | 713 | ** WEBPAGE: setup_timeline |
| 714 | 714 | ** |
| @@ -843,11 +843,11 @@ | ||
| 843 | 843 | |
| 844 | 844 | @ <hr /> |
| 845 | 845 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 846 | 846 | @ </div></form> |
| 847 | 847 | db_end_transaction(0); |
| 848 | - style_footer(); | |
| 848 | + style_finish_page("setup"); | |
| 849 | 849 | } |
| 850 | 850 | |
| 851 | 851 | /* |
| 852 | 852 | ** WEBPAGE: setup_settings |
| 853 | 853 | ** |
| @@ -936,11 +936,11 @@ | ||
| 936 | 936 | } |
| 937 | 937 | } |
| 938 | 938 | @ </td></tr></table> |
| 939 | 939 | @ </div></form> |
| 940 | 940 | db_end_transaction(0); |
| 941 | - style_footer(); | |
| 941 | + style_finish_page("setup"); | |
| 942 | 942 | } |
| 943 | 943 | |
| 944 | 944 | /* |
| 945 | 945 | ** WEBPAGE: setup_config |
| 946 | 946 | ** |
| @@ -1032,11 +1032,11 @@ | ||
| 1032 | 1032 | @ (Property: sitemap-contact) |
| 1033 | 1033 | @ <hr /> |
| 1034 | 1034 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1035 | 1035 | @ </div></form> |
| 1036 | 1036 | db_end_transaction(0); |
| 1037 | - style_footer(); | |
| 1037 | + style_finish_page("setup"); | |
| 1038 | 1038 | } |
| 1039 | 1039 | |
| 1040 | 1040 | /* |
| 1041 | 1041 | ** WEBPAGE: setup_wiki |
| 1042 | 1042 | ** |
| @@ -1108,11 +1108,11 @@ | ||
| 1108 | 1108 | @ (Property: "wiki-use-html") |
| 1109 | 1109 | @ <hr /> |
| 1110 | 1110 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1111 | 1111 | @ </div></form> |
| 1112 | 1112 | db_end_transaction(0); |
| 1113 | - style_footer(); | |
| 1113 | + style_finish_page("setup"); | |
| 1114 | 1114 | } |
| 1115 | 1115 | |
| 1116 | 1116 | /* |
| 1117 | 1117 | ** WEBPAGE: setup_modreq |
| 1118 | 1118 | ** |
| @@ -1154,11 +1154,11 @@ | ||
| 1154 | 1154 | |
| 1155 | 1155 | @ <hr /> |
| 1156 | 1156 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1157 | 1157 | @ </div></form> |
| 1158 | 1158 | db_end_transaction(0); |
| 1159 | - style_footer(); | |
| 1159 | + style_finish_page("setup"); | |
| 1160 | 1160 | |
| 1161 | 1161 | } |
| 1162 | 1162 | |
| 1163 | 1163 | /* |
| 1164 | 1164 | ** WEBPAGE: setup_adunit |
| @@ -1235,11 +1235,11 @@ | ||
| 1235 | 1235 | @ border: 1px solid #f11; |
| 1236 | 1236 | @ background-color: #fcc; |
| 1237 | 1237 | @ '>Demo Ad</div> |
| 1238 | 1238 | @ </pre></blockquote> |
| 1239 | 1239 | @ </li> |
| 1240 | - style_footer(); | |
| 1240 | + style_finish_page("setup"); | |
| 1241 | 1241 | db_end_transaction(0); |
| 1242 | 1242 | } |
| 1243 | 1243 | |
| 1244 | 1244 | /* |
| 1245 | 1245 | ** WEBPAGE: setup_logo |
| @@ -1437,11 +1437,11 @@ | ||
| 1437 | 1437 | @ <hr /> |
| 1438 | 1438 | @ |
| 1439 | 1439 | @ <p><span class="note">Note:</span> Your browser has probably cached these |
| 1440 | 1440 | @ images, so you may need to press the Reload button before changes will |
| 1441 | 1441 | @ take effect. </p> |
| 1442 | - style_footer(); | |
| 1442 | + style_finish_page("setup"); | |
| 1443 | 1443 | db_end_transaction(0); |
| 1444 | 1444 | } |
| 1445 | 1445 | |
| 1446 | 1446 | /* |
| 1447 | 1447 | ** Prevent the RAW SQL feature from being used to ATTACH a different |
| @@ -1599,11 +1599,11 @@ | ||
| 1599 | 1599 | } |
| 1600 | 1600 | sqlite3_finalize(pStmt); |
| 1601 | 1601 | @ </table> |
| 1602 | 1602 | } |
| 1603 | 1603 | } |
| 1604 | - style_footer(); | |
| 1604 | + style_finish_page("setup"); | |
| 1605 | 1605 | } |
| 1606 | 1606 | |
| 1607 | 1607 | |
| 1608 | 1608 | /* |
| 1609 | 1609 | ** WEBPAGE: admin_th1 |
| @@ -1643,11 +1643,11 @@ | ||
| 1643 | 1643 | @ <pre class="th1result">%h(zR)</pre> |
| 1644 | 1644 | }else{ |
| 1645 | 1645 | @ <pre class="th1error">%h(zR)</pre> |
| 1646 | 1646 | } |
| 1647 | 1647 | } |
| 1648 | - style_footer(); | |
| 1648 | + style_finish_page("setup"); | |
| 1649 | 1649 | } |
| 1650 | 1650 | |
| 1651 | 1651 | /* |
| 1652 | 1652 | ** WEBPAGE: admin_log |
| 1653 | 1653 | ** |
| @@ -1710,11 +1710,11 @@ | ||
| 1710 | 1710 | db_finalize(&stLog); |
| 1711 | 1711 | @ </tbody></table> |
| 1712 | 1712 | if( counter>ofst+limit ){ |
| 1713 | 1713 | @ <p><a href="admin_log?n=%d(limit)&x=%d(limit+ofst)">[Older]</a></p> |
| 1714 | 1714 | } |
| 1715 | - style_footer(); | |
| 1715 | + style_finish_page("setup"); | |
| 1716 | 1716 | } |
| 1717 | 1717 | |
| 1718 | 1718 | /* |
| 1719 | 1719 | ** WEBPAGE: srchsetup |
| 1720 | 1720 | ** |
| @@ -1790,11 +1790,11 @@ | ||
| 1790 | 1790 | @ larger repositories.</p> |
| 1791 | 1791 | onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0); |
| 1792 | 1792 | @ <p><input type="submit" name="fts1" value="Create A Full-Text Index"> |
| 1793 | 1793 | } |
| 1794 | 1794 | @ </div></form> |
| 1795 | - style_footer(); | |
| 1795 | + style_finish_page("setup"); | |
| 1796 | 1796 | } |
| 1797 | 1797 | |
| 1798 | 1798 | /* |
| 1799 | 1799 | ** A URL Alias originally called zOldName is now zNewName/zValue. |
| 1800 | 1800 | ** Write SQL to make this change into pSql. |
| @@ -1948,7 +1948,7 @@ | ||
| 1948 | 1948 | @ <p>To delete an entry from the alias table, change its name or value to an |
| 1949 | 1949 | @ empty string and press "Apply Changes". |
| 1950 | 1950 | @ |
| 1951 | 1951 | @ <p>To add a new alias, fill in the name and value in the bottom row |
| 1952 | 1952 | @ of the table above and press "Apply Changes". |
| 1953 | - style_footer(); | |
| 1953 | + style_finish_page("setup"); | |
| 1954 | 1954 | } |
| 1955 | 1955 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -175,11 +175,11 @@ | |
| 175 | setup_menu_entry("TH1", "admin_th1", |
| 176 | "Enter raw TH1 commands"); |
| 177 | } |
| 178 | @ </table> |
| 179 | |
| 180 | style_footer(); |
| 181 | } |
| 182 | |
| 183 | /* |
| 184 | ** Generate a checkbox for an attribute. |
| 185 | */ |
| @@ -576,11 +576,11 @@ | |
| 576 | |
| 577 | @ <hr /> |
| 578 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 579 | @ </div></form> |
| 580 | db_end_transaction(0); |
| 581 | style_footer(); |
| 582 | } |
| 583 | |
| 584 | /* |
| 585 | ** WEBPAGE: setup_login_group |
| 586 | ** |
| @@ -704,11 +704,11 @@ | |
| 704 | } |
| 705 | db_finalize(&q); |
| 706 | @ </tbody></table> |
| 707 | style_table_sorter(); |
| 708 | } |
| 709 | style_footer(); |
| 710 | } |
| 711 | |
| 712 | /* |
| 713 | ** WEBPAGE: setup_timeline |
| 714 | ** |
| @@ -843,11 +843,11 @@ | |
| 843 | |
| 844 | @ <hr /> |
| 845 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 846 | @ </div></form> |
| 847 | db_end_transaction(0); |
| 848 | style_footer(); |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | ** WEBPAGE: setup_settings |
| 853 | ** |
| @@ -936,11 +936,11 @@ | |
| 936 | } |
| 937 | } |
| 938 | @ </td></tr></table> |
| 939 | @ </div></form> |
| 940 | db_end_transaction(0); |
| 941 | style_footer(); |
| 942 | } |
| 943 | |
| 944 | /* |
| 945 | ** WEBPAGE: setup_config |
| 946 | ** |
| @@ -1032,11 +1032,11 @@ | |
| 1032 | @ (Property: sitemap-contact) |
| 1033 | @ <hr /> |
| 1034 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1035 | @ </div></form> |
| 1036 | db_end_transaction(0); |
| 1037 | style_footer(); |
| 1038 | } |
| 1039 | |
| 1040 | /* |
| 1041 | ** WEBPAGE: setup_wiki |
| 1042 | ** |
| @@ -1108,11 +1108,11 @@ | |
| 1108 | @ (Property: "wiki-use-html") |
| 1109 | @ <hr /> |
| 1110 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1111 | @ </div></form> |
| 1112 | db_end_transaction(0); |
| 1113 | style_footer(); |
| 1114 | } |
| 1115 | |
| 1116 | /* |
| 1117 | ** WEBPAGE: setup_modreq |
| 1118 | ** |
| @@ -1154,11 +1154,11 @@ | |
| 1154 | |
| 1155 | @ <hr /> |
| 1156 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1157 | @ </div></form> |
| 1158 | db_end_transaction(0); |
| 1159 | style_footer(); |
| 1160 | |
| 1161 | } |
| 1162 | |
| 1163 | /* |
| 1164 | ** WEBPAGE: setup_adunit |
| @@ -1235,11 +1235,11 @@ | |
| 1235 | @ border: 1px solid #f11; |
| 1236 | @ background-color: #fcc; |
| 1237 | @ '>Demo Ad</div> |
| 1238 | @ </pre></blockquote> |
| 1239 | @ </li> |
| 1240 | style_footer(); |
| 1241 | db_end_transaction(0); |
| 1242 | } |
| 1243 | |
| 1244 | /* |
| 1245 | ** WEBPAGE: setup_logo |
| @@ -1437,11 +1437,11 @@ | |
| 1437 | @ <hr /> |
| 1438 | @ |
| 1439 | @ <p><span class="note">Note:</span> Your browser has probably cached these |
| 1440 | @ images, so you may need to press the Reload button before changes will |
| 1441 | @ take effect. </p> |
| 1442 | style_footer(); |
| 1443 | db_end_transaction(0); |
| 1444 | } |
| 1445 | |
| 1446 | /* |
| 1447 | ** Prevent the RAW SQL feature from being used to ATTACH a different |
| @@ -1599,11 +1599,11 @@ | |
| 1599 | } |
| 1600 | sqlite3_finalize(pStmt); |
| 1601 | @ </table> |
| 1602 | } |
| 1603 | } |
| 1604 | style_footer(); |
| 1605 | } |
| 1606 | |
| 1607 | |
| 1608 | /* |
| 1609 | ** WEBPAGE: admin_th1 |
| @@ -1643,11 +1643,11 @@ | |
| 1643 | @ <pre class="th1result">%h(zR)</pre> |
| 1644 | }else{ |
| 1645 | @ <pre class="th1error">%h(zR)</pre> |
| 1646 | } |
| 1647 | } |
| 1648 | style_footer(); |
| 1649 | } |
| 1650 | |
| 1651 | /* |
| 1652 | ** WEBPAGE: admin_log |
| 1653 | ** |
| @@ -1710,11 +1710,11 @@ | |
| 1710 | db_finalize(&stLog); |
| 1711 | @ </tbody></table> |
| 1712 | if( counter>ofst+limit ){ |
| 1713 | @ <p><a href="admin_log?n=%d(limit)&x=%d(limit+ofst)">[Older]</a></p> |
| 1714 | } |
| 1715 | style_footer(); |
| 1716 | } |
| 1717 | |
| 1718 | /* |
| 1719 | ** WEBPAGE: srchsetup |
| 1720 | ** |
| @@ -1790,11 +1790,11 @@ | |
| 1790 | @ larger repositories.</p> |
| 1791 | onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0); |
| 1792 | @ <p><input type="submit" name="fts1" value="Create A Full-Text Index"> |
| 1793 | } |
| 1794 | @ </div></form> |
| 1795 | style_footer(); |
| 1796 | } |
| 1797 | |
| 1798 | /* |
| 1799 | ** A URL Alias originally called zOldName is now zNewName/zValue. |
| 1800 | ** Write SQL to make this change into pSql. |
| @@ -1948,7 +1948,7 @@ | |
| 1948 | @ <p>To delete an entry from the alias table, change its name or value to an |
| 1949 | @ empty string and press "Apply Changes". |
| 1950 | @ |
| 1951 | @ <p>To add a new alias, fill in the name and value in the bottom row |
| 1952 | @ of the table above and press "Apply Changes". |
| 1953 | style_footer(); |
| 1954 | } |
| 1955 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -175,11 +175,11 @@ | |
| 175 | setup_menu_entry("TH1", "admin_th1", |
| 176 | "Enter raw TH1 commands"); |
| 177 | } |
| 178 | @ </table> |
| 179 | |
| 180 | style_finish_page("setup"); |
| 181 | } |
| 182 | |
| 183 | /* |
| 184 | ** Generate a checkbox for an attribute. |
| 185 | */ |
| @@ -576,11 +576,11 @@ | |
| 576 | |
| 577 | @ <hr /> |
| 578 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 579 | @ </div></form> |
| 580 | db_end_transaction(0); |
| 581 | style_finish_page("setup"); |
| 582 | } |
| 583 | |
| 584 | /* |
| 585 | ** WEBPAGE: setup_login_group |
| 586 | ** |
| @@ -704,11 +704,11 @@ | |
| 704 | } |
| 705 | db_finalize(&q); |
| 706 | @ </tbody></table> |
| 707 | style_table_sorter(); |
| 708 | } |
| 709 | style_finish_page("setup"); |
| 710 | } |
| 711 | |
| 712 | /* |
| 713 | ** WEBPAGE: setup_timeline |
| 714 | ** |
| @@ -843,11 +843,11 @@ | |
| 843 | |
| 844 | @ <hr /> |
| 845 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 846 | @ </div></form> |
| 847 | db_end_transaction(0); |
| 848 | style_finish_page("setup"); |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | ** WEBPAGE: setup_settings |
| 853 | ** |
| @@ -936,11 +936,11 @@ | |
| 936 | } |
| 937 | } |
| 938 | @ </td></tr></table> |
| 939 | @ </div></form> |
| 940 | db_end_transaction(0); |
| 941 | style_finish_page("setup"); |
| 942 | } |
| 943 | |
| 944 | /* |
| 945 | ** WEBPAGE: setup_config |
| 946 | ** |
| @@ -1032,11 +1032,11 @@ | |
| 1032 | @ (Property: sitemap-contact) |
| 1033 | @ <hr /> |
| 1034 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1035 | @ </div></form> |
| 1036 | db_end_transaction(0); |
| 1037 | style_finish_page("setup"); |
| 1038 | } |
| 1039 | |
| 1040 | /* |
| 1041 | ** WEBPAGE: setup_wiki |
| 1042 | ** |
| @@ -1108,11 +1108,11 @@ | |
| 1108 | @ (Property: "wiki-use-html") |
| 1109 | @ <hr /> |
| 1110 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1111 | @ </div></form> |
| 1112 | db_end_transaction(0); |
| 1113 | style_finish_page("setup"); |
| 1114 | } |
| 1115 | |
| 1116 | /* |
| 1117 | ** WEBPAGE: setup_modreq |
| 1118 | ** |
| @@ -1154,11 +1154,11 @@ | |
| 1154 | |
| 1155 | @ <hr /> |
| 1156 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 1157 | @ </div></form> |
| 1158 | db_end_transaction(0); |
| 1159 | style_finish_page("setup"); |
| 1160 | |
| 1161 | } |
| 1162 | |
| 1163 | /* |
| 1164 | ** WEBPAGE: setup_adunit |
| @@ -1235,11 +1235,11 @@ | |
| 1235 | @ border: 1px solid #f11; |
| 1236 | @ background-color: #fcc; |
| 1237 | @ '>Demo Ad</div> |
| 1238 | @ </pre></blockquote> |
| 1239 | @ </li> |
| 1240 | style_finish_page("setup"); |
| 1241 | db_end_transaction(0); |
| 1242 | } |
| 1243 | |
| 1244 | /* |
| 1245 | ** WEBPAGE: setup_logo |
| @@ -1437,11 +1437,11 @@ | |
| 1437 | @ <hr /> |
| 1438 | @ |
| 1439 | @ <p><span class="note">Note:</span> Your browser has probably cached these |
| 1440 | @ images, so you may need to press the Reload button before changes will |
| 1441 | @ take effect. </p> |
| 1442 | style_finish_page("setup"); |
| 1443 | db_end_transaction(0); |
| 1444 | } |
| 1445 | |
| 1446 | /* |
| 1447 | ** Prevent the RAW SQL feature from being used to ATTACH a different |
| @@ -1599,11 +1599,11 @@ | |
| 1599 | } |
| 1600 | sqlite3_finalize(pStmt); |
| 1601 | @ </table> |
| 1602 | } |
| 1603 | } |
| 1604 | style_finish_page("setup"); |
| 1605 | } |
| 1606 | |
| 1607 | |
| 1608 | /* |
| 1609 | ** WEBPAGE: admin_th1 |
| @@ -1643,11 +1643,11 @@ | |
| 1643 | @ <pre class="th1result">%h(zR)</pre> |
| 1644 | }else{ |
| 1645 | @ <pre class="th1error">%h(zR)</pre> |
| 1646 | } |
| 1647 | } |
| 1648 | style_finish_page("setup"); |
| 1649 | } |
| 1650 | |
| 1651 | /* |
| 1652 | ** WEBPAGE: admin_log |
| 1653 | ** |
| @@ -1710,11 +1710,11 @@ | |
| 1710 | db_finalize(&stLog); |
| 1711 | @ </tbody></table> |
| 1712 | if( counter>ofst+limit ){ |
| 1713 | @ <p><a href="admin_log?n=%d(limit)&x=%d(limit+ofst)">[Older]</a></p> |
| 1714 | } |
| 1715 | style_finish_page("setup"); |
| 1716 | } |
| 1717 | |
| 1718 | /* |
| 1719 | ** WEBPAGE: srchsetup |
| 1720 | ** |
| @@ -1790,11 +1790,11 @@ | |
| 1790 | @ larger repositories.</p> |
| 1791 | onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0); |
| 1792 | @ <p><input type="submit" name="fts1" value="Create A Full-Text Index"> |
| 1793 | } |
| 1794 | @ </div></form> |
| 1795 | style_finish_page("setup"); |
| 1796 | } |
| 1797 | |
| 1798 | /* |
| 1799 | ** A URL Alias originally called zOldName is now zNewName/zValue. |
| 1800 | ** Write SQL to make this change into pSql. |
| @@ -1948,7 +1948,7 @@ | |
| 1948 | @ <p>To delete an entry from the alias table, change its name or value to an |
| 1949 | @ empty string and press "Apply Changes". |
| 1950 | @ |
| 1951 | @ <p>To add a new alias, fill in the name and value in the bottom row |
| 1952 | @ of the table above and press "Apply Changes". |
| 1953 | style_finish_page("setup"); |
| 1954 | } |
| 1955 |
+7
-7
| --- src/setupuser.c | ||
| +++ src/setupuser.c | ||
| @@ -180,11 +180,11 @@ | ||
| 180 | 180 | fossil_free(zAge); |
| 181 | 181 | } |
| 182 | 182 | @ </tbody></table> |
| 183 | 183 | db_finalize(&s); |
| 184 | 184 | style_table_sorter(); |
| 185 | - style_footer(); | |
| 185 | + style_finish_page("setupuser"); | |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | 188 | /* |
| 189 | 189 | ** WEBPAGE: setup_ulist_notes |
| 190 | 190 | ** |
| @@ -226,11 +226,11 @@ | ||
| 226 | 226 | @ |
| 227 | 227 | @ <li><p>The permission flags are as follows:</p> |
| 228 | 228 | capabilities_table(CAPCLASS_ALL); |
| 229 | 229 | @ </li> |
| 230 | 230 | @ </ol> |
| 231 | - style_footer(); | |
| 231 | + style_finish_page("setupuser"); | |
| 232 | 232 | } |
| 233 | 233 | |
| 234 | 234 | /* |
| 235 | 235 | ** WEBPAGE: setup_ucap_list |
| 236 | 236 | ** |
| @@ -253,11 +253,11 @@ | ||
| 253 | 253 | capabilities_table(CAPCLASS_WIKI); |
| 254 | 254 | @ <h1>Administrative capabilities</h1> |
| 255 | 255 | capabilities_table(CAPCLASS_SUPER); |
| 256 | 256 | @ <h1>Miscellaneous capabilities</h1> |
| 257 | 257 | capabilities_table(CAPCLASS_OTHER); |
| 258 | - style_footer(); | |
| 258 | + style_finish_page("setupuser"); | |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | 261 | /* |
| 262 | 262 | ** Return true if zPw is a valid password string. A valid |
| 263 | 263 | ** password string is: |
| @@ -387,11 +387,11 @@ | ||
| 387 | 387 | style_header("User Creation Error"); |
| 388 | 388 | @ <span class="loginError">Empty login not allowed.</span> |
| 389 | 389 | @ |
| 390 | 390 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 391 | 391 | @ [Bummer]</a></p> |
| 392 | - style_footer(); | |
| 392 | + style_finish_page("setupuser"); | |
| 393 | 393 | return; |
| 394 | 394 | } |
| 395 | 395 | if( isValidPwString(zPw) ){ |
| 396 | 396 | zPw = sha1_shared_secret(zPw, zLogin, 0); |
| 397 | 397 | }else{ |
| @@ -404,11 +404,11 @@ | ||
| 404 | 404 | @ <span class="loginError">Login "%h(zLogin)" is already used by |
| 405 | 405 | @ a different user.</span> |
| 406 | 406 | @ |
| 407 | 407 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 408 | 408 | @ [Bummer]</a></p> |
| 409 | - style_footer(); | |
| 409 | + style_finish_page("setupuser"); | |
| 410 | 410 | return; |
| 411 | 411 | } |
| 412 | 412 | login_verify_csrf_secret(); |
| 413 | 413 | db_unprotect(PROTECT_USER); |
| 414 | 414 | db_multi_exec( |
| @@ -456,11 +456,11 @@ | ||
| 456 | 456 | admin_log( "Error updating user '%q': %s'.", zLogin, zErr ); |
| 457 | 457 | @ <span class="loginError">%h(zErr)</span> |
| 458 | 458 | @ |
| 459 | 459 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 460 | 460 | @ [Bummer]</a></p> |
| 461 | - style_footer(); | |
| 461 | + style_finish_page("setupuser"); | |
| 462 | 462 | return; |
| 463 | 463 | } |
| 464 | 464 | } |
| 465 | 465 | cgi_redirect(cgi_referer("setup_ulist")); |
| 466 | 466 | return; |
| @@ -874,7 +874,7 @@ | ||
| 874 | 874 | @ template for users who are allowed more access than |
| 875 | 875 | @ <span class="usertype">anonymous</span>, |
| 876 | 876 | @ but less than a <span class="usertype">developer</span>. |
| 877 | 877 | @ </p></li> |
| 878 | 878 | @ </ul> |
| 879 | - style_footer(); | |
| 879 | + style_finish_page("setupuser"); | |
| 880 | 880 | } |
| 881 | 881 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -180,11 +180,11 @@ | |
| 180 | fossil_free(zAge); |
| 181 | } |
| 182 | @ </tbody></table> |
| 183 | db_finalize(&s); |
| 184 | style_table_sorter(); |
| 185 | style_footer(); |
| 186 | } |
| 187 | |
| 188 | /* |
| 189 | ** WEBPAGE: setup_ulist_notes |
| 190 | ** |
| @@ -226,11 +226,11 @@ | |
| 226 | @ |
| 227 | @ <li><p>The permission flags are as follows:</p> |
| 228 | capabilities_table(CAPCLASS_ALL); |
| 229 | @ </li> |
| 230 | @ </ol> |
| 231 | style_footer(); |
| 232 | } |
| 233 | |
| 234 | /* |
| 235 | ** WEBPAGE: setup_ucap_list |
| 236 | ** |
| @@ -253,11 +253,11 @@ | |
| 253 | capabilities_table(CAPCLASS_WIKI); |
| 254 | @ <h1>Administrative capabilities</h1> |
| 255 | capabilities_table(CAPCLASS_SUPER); |
| 256 | @ <h1>Miscellaneous capabilities</h1> |
| 257 | capabilities_table(CAPCLASS_OTHER); |
| 258 | style_footer(); |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | ** Return true if zPw is a valid password string. A valid |
| 263 | ** password string is: |
| @@ -387,11 +387,11 @@ | |
| 387 | style_header("User Creation Error"); |
| 388 | @ <span class="loginError">Empty login not allowed.</span> |
| 389 | @ |
| 390 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 391 | @ [Bummer]</a></p> |
| 392 | style_footer(); |
| 393 | return; |
| 394 | } |
| 395 | if( isValidPwString(zPw) ){ |
| 396 | zPw = sha1_shared_secret(zPw, zLogin, 0); |
| 397 | }else{ |
| @@ -404,11 +404,11 @@ | |
| 404 | @ <span class="loginError">Login "%h(zLogin)" is already used by |
| 405 | @ a different user.</span> |
| 406 | @ |
| 407 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 408 | @ [Bummer]</a></p> |
| 409 | style_footer(); |
| 410 | return; |
| 411 | } |
| 412 | login_verify_csrf_secret(); |
| 413 | db_unprotect(PROTECT_USER); |
| 414 | db_multi_exec( |
| @@ -456,11 +456,11 @@ | |
| 456 | admin_log( "Error updating user '%q': %s'.", zLogin, zErr ); |
| 457 | @ <span class="loginError">%h(zErr)</span> |
| 458 | @ |
| 459 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 460 | @ [Bummer]</a></p> |
| 461 | style_footer(); |
| 462 | return; |
| 463 | } |
| 464 | } |
| 465 | cgi_redirect(cgi_referer("setup_ulist")); |
| 466 | return; |
| @@ -874,7 +874,7 @@ | |
| 874 | @ template for users who are allowed more access than |
| 875 | @ <span class="usertype">anonymous</span>, |
| 876 | @ but less than a <span class="usertype">developer</span>. |
| 877 | @ </p></li> |
| 878 | @ </ul> |
| 879 | style_footer(); |
| 880 | } |
| 881 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -180,11 +180,11 @@ | |
| 180 | fossil_free(zAge); |
| 181 | } |
| 182 | @ </tbody></table> |
| 183 | db_finalize(&s); |
| 184 | style_table_sorter(); |
| 185 | style_finish_page("setupuser"); |
| 186 | } |
| 187 | |
| 188 | /* |
| 189 | ** WEBPAGE: setup_ulist_notes |
| 190 | ** |
| @@ -226,11 +226,11 @@ | |
| 226 | @ |
| 227 | @ <li><p>The permission flags are as follows:</p> |
| 228 | capabilities_table(CAPCLASS_ALL); |
| 229 | @ </li> |
| 230 | @ </ol> |
| 231 | style_finish_page("setupuser"); |
| 232 | } |
| 233 | |
| 234 | /* |
| 235 | ** WEBPAGE: setup_ucap_list |
| 236 | ** |
| @@ -253,11 +253,11 @@ | |
| 253 | capabilities_table(CAPCLASS_WIKI); |
| 254 | @ <h1>Administrative capabilities</h1> |
| 255 | capabilities_table(CAPCLASS_SUPER); |
| 256 | @ <h1>Miscellaneous capabilities</h1> |
| 257 | capabilities_table(CAPCLASS_OTHER); |
| 258 | style_finish_page("setupuser"); |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | ** Return true if zPw is a valid password string. A valid |
| 263 | ** password string is: |
| @@ -387,11 +387,11 @@ | |
| 387 | style_header("User Creation Error"); |
| 388 | @ <span class="loginError">Empty login not allowed.</span> |
| 389 | @ |
| 390 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 391 | @ [Bummer]</a></p> |
| 392 | style_finish_page("setupuser"); |
| 393 | return; |
| 394 | } |
| 395 | if( isValidPwString(zPw) ){ |
| 396 | zPw = sha1_shared_secret(zPw, zLogin, 0); |
| 397 | }else{ |
| @@ -404,11 +404,11 @@ | |
| 404 | @ <span class="loginError">Login "%h(zLogin)" is already used by |
| 405 | @ a different user.</span> |
| 406 | @ |
| 407 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 408 | @ [Bummer]</a></p> |
| 409 | style_finish_page("setupuser"); |
| 410 | return; |
| 411 | } |
| 412 | login_verify_csrf_secret(); |
| 413 | db_unprotect(PROTECT_USER); |
| 414 | db_multi_exec( |
| @@ -456,11 +456,11 @@ | |
| 456 | admin_log( "Error updating user '%q': %s'.", zLogin, zErr ); |
| 457 | @ <span class="loginError">%h(zErr)</span> |
| 458 | @ |
| 459 | @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)"> |
| 460 | @ [Bummer]</a></p> |
| 461 | style_finish_page("setupuser"); |
| 462 | return; |
| 463 | } |
| 464 | } |
| 465 | cgi_redirect(cgi_referer("setup_ulist")); |
| 466 | return; |
| @@ -874,7 +874,7 @@ | |
| 874 | @ template for users who are allowed more access than |
| 875 | @ <span class="usertype">anonymous</span>, |
| 876 | @ but less than a <span class="usertype">developer</span>. |
| 877 | @ </p></li> |
| 878 | @ </ul> |
| 879 | style_finish_page("setupuser"); |
| 880 | } |
| 881 |
+7
-4
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -20717,10 +20717,11 @@ | ||
| 20717 | 20717 | #ifdef SQLITE_ENABLE_SORTER_REFERENCES |
| 20718 | 20718 | " -sorterref SIZE sorter references threshold size\n" |
| 20719 | 20719 | #endif |
| 20720 | 20720 | " -stats print memory stats before each finalize\n" |
| 20721 | 20721 | " -table set output mode to 'table'\n" |
| 20722 | + " -tabs set output mode to 'tabs'\n" | |
| 20722 | 20723 | " -version show SQLite version\n" |
| 20723 | 20724 | " -vfs NAME use NAME as the default VFS\n" |
| 20724 | 20725 | #ifdef SQLITE_ENABLE_VFSTRACE |
| 20725 | 20726 | " -vfstrace enable tracing of all VFS calls\n" |
| 20726 | 20727 | #endif |
| @@ -21152,14 +21153,16 @@ | ||
| 21152 | 21153 | data.openMode = SHELL_OPEN_READONLY; |
| 21153 | 21154 | }else if( strcmp(z,"-nofollow")==0 ){ |
| 21154 | 21155 | data.openFlags |= SQLITE_OPEN_NOFOLLOW; |
| 21155 | 21156 | }else if( strcmp(z,"-ascii")==0 ){ |
| 21156 | 21157 | data.mode = MODE_Ascii; |
| 21157 | - sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, | |
| 21158 | - SEP_Unit); | |
| 21159 | - sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, | |
| 21160 | - SEP_Record); | |
| 21158 | + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit); | |
| 21159 | + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record); | |
| 21160 | + }else if( strcmp(z,"-tabs")==0 ){ | |
| 21161 | + data.mode = MODE_List; | |
| 21162 | + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab); | |
| 21163 | + sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row); | |
| 21161 | 21164 | }else if( strcmp(z,"-separator")==0 ){ |
| 21162 | 21165 | sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, |
| 21163 | 21166 | "%s",cmdline_option_value(argc,argv,++i)); |
| 21164 | 21167 | }else if( strcmp(z,"-newline")==0 ){ |
| 21165 | 21168 | sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, |
| 21166 | 21169 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -20717,10 +20717,11 @@ | |
| 20717 | #ifdef SQLITE_ENABLE_SORTER_REFERENCES |
| 20718 | " -sorterref SIZE sorter references threshold size\n" |
| 20719 | #endif |
| 20720 | " -stats print memory stats before each finalize\n" |
| 20721 | " -table set output mode to 'table'\n" |
| 20722 | " -version show SQLite version\n" |
| 20723 | " -vfs NAME use NAME as the default VFS\n" |
| 20724 | #ifdef SQLITE_ENABLE_VFSTRACE |
| 20725 | " -vfstrace enable tracing of all VFS calls\n" |
| 20726 | #endif |
| @@ -21152,14 +21153,16 @@ | |
| 21152 | data.openMode = SHELL_OPEN_READONLY; |
| 21153 | }else if( strcmp(z,"-nofollow")==0 ){ |
| 21154 | data.openFlags |= SQLITE_OPEN_NOFOLLOW; |
| 21155 | }else if( strcmp(z,"-ascii")==0 ){ |
| 21156 | data.mode = MODE_Ascii; |
| 21157 | sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, |
| 21158 | SEP_Unit); |
| 21159 | sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, |
| 21160 | SEP_Record); |
| 21161 | }else if( strcmp(z,"-separator")==0 ){ |
| 21162 | sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, |
| 21163 | "%s",cmdline_option_value(argc,argv,++i)); |
| 21164 | }else if( strcmp(z,"-newline")==0 ){ |
| 21165 | sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, |
| 21166 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -20717,10 +20717,11 @@ | |
| 20717 | #ifdef SQLITE_ENABLE_SORTER_REFERENCES |
| 20718 | " -sorterref SIZE sorter references threshold size\n" |
| 20719 | #endif |
| 20720 | " -stats print memory stats before each finalize\n" |
| 20721 | " -table set output mode to 'table'\n" |
| 20722 | " -tabs set output mode to 'tabs'\n" |
| 20723 | " -version show SQLite version\n" |
| 20724 | " -vfs NAME use NAME as the default VFS\n" |
| 20725 | #ifdef SQLITE_ENABLE_VFSTRACE |
| 20726 | " -vfstrace enable tracing of all VFS calls\n" |
| 20727 | #endif |
| @@ -21152,14 +21153,16 @@ | |
| 21153 | data.openMode = SHELL_OPEN_READONLY; |
| 21154 | }else if( strcmp(z,"-nofollow")==0 ){ |
| 21155 | data.openFlags |= SQLITE_OPEN_NOFOLLOW; |
| 21156 | }else if( strcmp(z,"-ascii")==0 ){ |
| 21157 | data.mode = MODE_Ascii; |
| 21158 | sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit); |
| 21159 | sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record); |
| 21160 | }else if( strcmp(z,"-tabs")==0 ){ |
| 21161 | data.mode = MODE_List; |
| 21162 | sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab); |
| 21163 | sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row); |
| 21164 | }else if( strcmp(z,"-separator")==0 ){ |
| 21165 | sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, |
| 21166 | "%s",cmdline_option_value(argc,argv,++i)); |
| 21167 | }else if( strcmp(z,"-newline")==0 ){ |
| 21168 | sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, |
| 21169 |
+3
-3
| --- src/shun.c | ||
| +++ src/shun.c | ||
| @@ -263,11 +263,11 @@ | ||
| 263 | 263 | if( cnt==0 ){ |
| 264 | 264 | @ <i>no artifacts are shunned on this server</i> |
| 265 | 265 | } |
| 266 | 266 | db_finalize(&q); |
| 267 | 267 | @ </p></blockquote> |
| 268 | - style_footer(); | |
| 268 | + style_finish_page("shun"); | |
| 269 | 269 | fossil_free(zCanonical); |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | /* |
| 273 | 273 | ** Remove from the BLOB table all artifacts that are in the SHUN table. |
| @@ -403,11 +403,11 @@ | ||
| 403 | 403 | @ </tr> |
| 404 | 404 | } |
| 405 | 405 | } |
| 406 | 406 | db_finalize(&q); |
| 407 | 407 | @ </table> |
| 408 | - style_footer(); | |
| 408 | + style_finish_page("rcvfromlist"); | |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | 411 | /* |
| 412 | 412 | ** WEBPAGE: rcvfrom |
| 413 | 413 | ** |
| @@ -549,7 +549,7 @@ | ||
| 549 | 549 | @ </td></tr> |
| 550 | 550 | } |
| 551 | 551 | } |
| 552 | 552 | @ </table> |
| 553 | 553 | db_finalize(&q); |
| 554 | - style_footer(); | |
| 554 | + style_finish_page("rcvfrom"); | |
| 555 | 555 | } |
| 556 | 556 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -263,11 +263,11 @@ | |
| 263 | if( cnt==0 ){ |
| 264 | @ <i>no artifacts are shunned on this server</i> |
| 265 | } |
| 266 | db_finalize(&q); |
| 267 | @ </p></blockquote> |
| 268 | style_footer(); |
| 269 | fossil_free(zCanonical); |
| 270 | } |
| 271 | |
| 272 | /* |
| 273 | ** Remove from the BLOB table all artifacts that are in the SHUN table. |
| @@ -403,11 +403,11 @@ | |
| 403 | @ </tr> |
| 404 | } |
| 405 | } |
| 406 | db_finalize(&q); |
| 407 | @ </table> |
| 408 | style_footer(); |
| 409 | } |
| 410 | |
| 411 | /* |
| 412 | ** WEBPAGE: rcvfrom |
| 413 | ** |
| @@ -549,7 +549,7 @@ | |
| 549 | @ </td></tr> |
| 550 | } |
| 551 | } |
| 552 | @ </table> |
| 553 | db_finalize(&q); |
| 554 | style_footer(); |
| 555 | } |
| 556 |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -263,11 +263,11 @@ | |
| 263 | if( cnt==0 ){ |
| 264 | @ <i>no artifacts are shunned on this server</i> |
| 265 | } |
| 266 | db_finalize(&q); |
| 267 | @ </p></blockquote> |
| 268 | style_finish_page("shun"); |
| 269 | fossil_free(zCanonical); |
| 270 | } |
| 271 | |
| 272 | /* |
| 273 | ** Remove from the BLOB table all artifacts that are in the SHUN table. |
| @@ -403,11 +403,11 @@ | |
| 403 | @ </tr> |
| 404 | } |
| 405 | } |
| 406 | db_finalize(&q); |
| 407 | @ </table> |
| 408 | style_finish_page("rcvfromlist"); |
| 409 | } |
| 410 | |
| 411 | /* |
| 412 | ** WEBPAGE: rcvfrom |
| 413 | ** |
| @@ -549,7 +549,7 @@ | |
| 549 | @ </td></tr> |
| 550 | } |
| 551 | } |
| 552 | @ </table> |
| 553 | db_finalize(&q); |
| 554 | style_finish_page("rcvfrom"); |
| 555 | } |
| 556 |
+1
-1
| --- src/sitemap.c | ||
| +++ src/sitemap.c | ||
| @@ -233,8 +233,8 @@ | ||
| 233 | 233 | @ colors assigned to branch names</a> |
| 234 | 234 | @ <li>%z(href("%R/test-captcha"))Random ASCII-art Captcha image</a></li> |
| 235 | 235 | @ </ul></li> |
| 236 | 236 | @ </ul> |
| 237 | 237 | if( !isPopup ){ |
| 238 | - style_footer(); | |
| 238 | + style_finish_page("sitemap"); | |
| 239 | 239 | } |
| 240 | 240 | } |
| 241 | 241 |
| --- src/sitemap.c | |
| +++ src/sitemap.c | |
| @@ -233,8 +233,8 @@ | |
| 233 | @ colors assigned to branch names</a> |
| 234 | @ <li>%z(href("%R/test-captcha"))Random ASCII-art Captcha image</a></li> |
| 235 | @ </ul></li> |
| 236 | @ </ul> |
| 237 | if( !isPopup ){ |
| 238 | style_footer(); |
| 239 | } |
| 240 | } |
| 241 |
| --- src/sitemap.c | |
| +++ src/sitemap.c | |
| @@ -233,8 +233,8 @@ | |
| 233 | @ colors assigned to branch names</a> |
| 234 | @ <li>%z(href("%R/test-captcha"))Random ASCII-art Captcha image</a></li> |
| 235 | @ </ul></li> |
| 236 | @ </ul> |
| 237 | if( !isPopup ){ |
| 238 | style_finish_page("sitemap"); |
| 239 | } |
| 240 | } |
| 241 |
+6
-6
| --- src/skins.c | ||
| +++ src/skins.c | ||
| @@ -401,11 +401,11 @@ | ||
| 401 | 401 | @ <input type="submit" name="rename" value="Rename"> |
| 402 | 402 | @ <input type="submit" name="canren" value="Cancel"> |
| 403 | 403 | @ </table> |
| 404 | 404 | login_insert_csrf_secret(); |
| 405 | 405 | @ </div></form> |
| 406 | - style_footer(); | |
| 406 | + style_finish_page("skins"); | |
| 407 | 407 | return 1; |
| 408 | 408 | } |
| 409 | 409 | db_unprotect(PROTECT_CONFIG); |
| 410 | 410 | db_multi_exec( |
| 411 | 411 | "UPDATE config SET name='skin:%q' WHERE name='skin:%q';", |
| @@ -441,11 +441,11 @@ | ||
| 441 | 441 | @ <input type="submit" name="save" value="Save"> |
| 442 | 442 | @ <input type="submit" name="cansave" value="Cancel"> |
| 443 | 443 | @ </table> |
| 444 | 444 | login_insert_csrf_secret(); |
| 445 | 445 | @ </div></form> |
| 446 | - style_footer(); | |
| 446 | + style_finish_page("skins"); | |
| 447 | 447 | return 1; |
| 448 | 448 | } |
| 449 | 449 | db_unprotect(PROTECT_CONFIG); |
| 450 | 450 | db_multi_exec( |
| 451 | 451 | "INSERT OR IGNORE INTO config(name, value, mtime)" |
| @@ -492,11 +492,11 @@ | ||
| 492 | 492 | @ <input type="hidden" name="sn" value="%h(P("sn"))" /> |
| 493 | 493 | @ <input type="submit" name="del2" value="Confirm - Delete The Skin" /> |
| 494 | 494 | @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" /> |
| 495 | 495 | login_insert_csrf_secret(); |
| 496 | 496 | @ </div></form> |
| 497 | - style_footer(); | |
| 497 | + style_finish_page("skins"); | |
| 498 | 498 | db_end_transaction(1); |
| 499 | 499 | return; |
| 500 | 500 | } |
| 501 | 501 | if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 502 | 502 | db_unprotect(PROTECT_CONFIG); |
| @@ -645,11 +645,11 @@ | ||
| 645 | 645 | @ </form></tr> |
| 646 | 646 | } |
| 647 | 647 | db_finalize(&q); |
| 648 | 648 | |
| 649 | 649 | @ </table> |
| 650 | - style_footer(); | |
| 650 | + style_finish_page("skins"); | |
| 651 | 651 | db_end_transaction(0); |
| 652 | 652 | } |
| 653 | 653 | |
| 654 | 654 | /* |
| 655 | 655 | ** Generate HTML for a <select> that lists all the available skin names, |
| @@ -842,11 +842,11 @@ | ||
| 842 | 842 | blob_reset(&from); |
| 843 | 843 | blob_reset(&to); |
| 844 | 844 | blob_reset(&out); |
| 845 | 845 | } |
| 846 | 846 | @ </div></form> |
| 847 | - style_footer(); | |
| 847 | + style_finish_page("skins"); | |
| 848 | 848 | db_end_transaction(0); |
| 849 | 849 | } |
| 850 | 850 | |
| 851 | 851 | /* |
| 852 | 852 | ** Try to initialize draft skin iSkin to the built-in or preexisting |
| @@ -1120,7 +1120,7 @@ | ||
| 1120 | 1120 | }else{ |
| 1121 | 1121 | @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page |
| 1122 | 1122 | @ for cleanup and recovery actions. |
| 1123 | 1123 | } |
| 1124 | 1124 | builtin_request_js("skin.js"); |
| 1125 | - style_footer(); | |
| 1125 | + style_finish_page("skins"); | |
| 1126 | 1126 | } |
| 1127 | 1127 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -401,11 +401,11 @@ | |
| 401 | @ <input type="submit" name="rename" value="Rename"> |
| 402 | @ <input type="submit" name="canren" value="Cancel"> |
| 403 | @ </table> |
| 404 | login_insert_csrf_secret(); |
| 405 | @ </div></form> |
| 406 | style_footer(); |
| 407 | return 1; |
| 408 | } |
| 409 | db_unprotect(PROTECT_CONFIG); |
| 410 | db_multi_exec( |
| 411 | "UPDATE config SET name='skin:%q' WHERE name='skin:%q';", |
| @@ -441,11 +441,11 @@ | |
| 441 | @ <input type="submit" name="save" value="Save"> |
| 442 | @ <input type="submit" name="cansave" value="Cancel"> |
| 443 | @ </table> |
| 444 | login_insert_csrf_secret(); |
| 445 | @ </div></form> |
| 446 | style_footer(); |
| 447 | return 1; |
| 448 | } |
| 449 | db_unprotect(PROTECT_CONFIG); |
| 450 | db_multi_exec( |
| 451 | "INSERT OR IGNORE INTO config(name, value, mtime)" |
| @@ -492,11 +492,11 @@ | |
| 492 | @ <input type="hidden" name="sn" value="%h(P("sn"))" /> |
| 493 | @ <input type="submit" name="del2" value="Confirm - Delete The Skin" /> |
| 494 | @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" /> |
| 495 | login_insert_csrf_secret(); |
| 496 | @ </div></form> |
| 497 | style_footer(); |
| 498 | db_end_transaction(1); |
| 499 | return; |
| 500 | } |
| 501 | if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 502 | db_unprotect(PROTECT_CONFIG); |
| @@ -645,11 +645,11 @@ | |
| 645 | @ </form></tr> |
| 646 | } |
| 647 | db_finalize(&q); |
| 648 | |
| 649 | @ </table> |
| 650 | style_footer(); |
| 651 | db_end_transaction(0); |
| 652 | } |
| 653 | |
| 654 | /* |
| 655 | ** Generate HTML for a <select> that lists all the available skin names, |
| @@ -842,11 +842,11 @@ | |
| 842 | blob_reset(&from); |
| 843 | blob_reset(&to); |
| 844 | blob_reset(&out); |
| 845 | } |
| 846 | @ </div></form> |
| 847 | style_footer(); |
| 848 | db_end_transaction(0); |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | ** Try to initialize draft skin iSkin to the built-in or preexisting |
| @@ -1120,7 +1120,7 @@ | |
| 1120 | }else{ |
| 1121 | @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page |
| 1122 | @ for cleanup and recovery actions. |
| 1123 | } |
| 1124 | builtin_request_js("skin.js"); |
| 1125 | style_footer(); |
| 1126 | } |
| 1127 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -401,11 +401,11 @@ | |
| 401 | @ <input type="submit" name="rename" value="Rename"> |
| 402 | @ <input type="submit" name="canren" value="Cancel"> |
| 403 | @ </table> |
| 404 | login_insert_csrf_secret(); |
| 405 | @ </div></form> |
| 406 | style_finish_page("skins"); |
| 407 | return 1; |
| 408 | } |
| 409 | db_unprotect(PROTECT_CONFIG); |
| 410 | db_multi_exec( |
| 411 | "UPDATE config SET name='skin:%q' WHERE name='skin:%q';", |
| @@ -441,11 +441,11 @@ | |
| 441 | @ <input type="submit" name="save" value="Save"> |
| 442 | @ <input type="submit" name="cansave" value="Cancel"> |
| 443 | @ </table> |
| 444 | login_insert_csrf_secret(); |
| 445 | @ </div></form> |
| 446 | style_finish_page("skins"); |
| 447 | return 1; |
| 448 | } |
| 449 | db_unprotect(PROTECT_CONFIG); |
| 450 | db_multi_exec( |
| 451 | "INSERT OR IGNORE INTO config(name, value, mtime)" |
| @@ -492,11 +492,11 @@ | |
| 492 | @ <input type="hidden" name="sn" value="%h(P("sn"))" /> |
| 493 | @ <input type="submit" name="del2" value="Confirm - Delete The Skin" /> |
| 494 | @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" /> |
| 495 | login_insert_csrf_secret(); |
| 496 | @ </div></form> |
| 497 | style_finish_page("skins"); |
| 498 | db_end_transaction(1); |
| 499 | return; |
| 500 | } |
| 501 | if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ |
| 502 | db_unprotect(PROTECT_CONFIG); |
| @@ -645,11 +645,11 @@ | |
| 645 | @ </form></tr> |
| 646 | } |
| 647 | db_finalize(&q); |
| 648 | |
| 649 | @ </table> |
| 650 | style_finish_page("skins"); |
| 651 | db_end_transaction(0); |
| 652 | } |
| 653 | |
| 654 | /* |
| 655 | ** Generate HTML for a <select> that lists all the available skin names, |
| @@ -842,11 +842,11 @@ | |
| 842 | blob_reset(&from); |
| 843 | blob_reset(&to); |
| 844 | blob_reset(&out); |
| 845 | } |
| 846 | @ </div></form> |
| 847 | style_finish_page("skins"); |
| 848 | db_end_transaction(0); |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | ** Try to initialize draft skin iSkin to the built-in or preexisting |
| @@ -1120,7 +1120,7 @@ | |
| 1120 | }else{ |
| 1121 | @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page |
| 1122 | @ for cleanup and recovery actions. |
| 1123 | } |
| 1124 | builtin_request_js("skin.js"); |
| 1125 | style_finish_page("skins"); |
| 1126 | } |
| 1127 |
+2
-2
| --- src/smtp.c | ||
| +++ src/smtp.c | ||
| @@ -805,11 +805,11 @@ | ||
| 805 | 805 | @ <form method="POST" action="%R/setup_smtp_route"> |
| 806 | 806 | @ <input type="submit" value="New"> |
| 807 | 807 | @ ← Add a new email address |
| 808 | 808 | @ </form> |
| 809 | 809 | @ </table> |
| 810 | - style_footer(); | |
| 810 | + style_finish_page("smtp"); | |
| 811 | 811 | db_end_transaction(0); |
| 812 | 812 | } |
| 813 | 813 | |
| 814 | 814 | /* |
| 815 | 815 | ** WEBPAGE: setup_smtp_route |
| @@ -924,11 +924,11 @@ | ||
| 924 | 924 | @ with USER.LOGIN=<i>login-name</i>. |
| 925 | 925 | @ </ul> |
| 926 | 926 | @ |
| 927 | 927 | @ <p>To delete a route → erase all text from the "Routing" field then |
| 928 | 928 | @ press the "Apply" button. |
| 929 | - style_footer(); | |
| 929 | + style_finish_page("smtp"); | |
| 930 | 930 | } |
| 931 | 931 | |
| 932 | 932 | #if LOCAL_INTERFACE |
| 933 | 933 | /* |
| 934 | 934 | ** State information for the server |
| 935 | 935 |
| --- src/smtp.c | |
| +++ src/smtp.c | |
| @@ -805,11 +805,11 @@ | |
| 805 | @ <form method="POST" action="%R/setup_smtp_route"> |
| 806 | @ <input type="submit" value="New"> |
| 807 | @ ← Add a new email address |
| 808 | @ </form> |
| 809 | @ </table> |
| 810 | style_footer(); |
| 811 | db_end_transaction(0); |
| 812 | } |
| 813 | |
| 814 | /* |
| 815 | ** WEBPAGE: setup_smtp_route |
| @@ -924,11 +924,11 @@ | |
| 924 | @ with USER.LOGIN=<i>login-name</i>. |
| 925 | @ </ul> |
| 926 | @ |
| 927 | @ <p>To delete a route → erase all text from the "Routing" field then |
| 928 | @ press the "Apply" button. |
| 929 | style_footer(); |
| 930 | } |
| 931 | |
| 932 | #if LOCAL_INTERFACE |
| 933 | /* |
| 934 | ** State information for the server |
| 935 |
| --- src/smtp.c | |
| +++ src/smtp.c | |
| @@ -805,11 +805,11 @@ | |
| 805 | @ <form method="POST" action="%R/setup_smtp_route"> |
| 806 | @ <input type="submit" value="New"> |
| 807 | @ ← Add a new email address |
| 808 | @ </form> |
| 809 | @ </table> |
| 810 | style_finish_page("smtp"); |
| 811 | db_end_transaction(0); |
| 812 | } |
| 813 | |
| 814 | /* |
| 815 | ** WEBPAGE: setup_smtp_route |
| @@ -924,11 +924,11 @@ | |
| 924 | @ with USER.LOGIN=<i>login-name</i>. |
| 925 | @ </ul> |
| 926 | @ |
| 927 | @ <p>To delete a route → erase all text from the "Routing" field then |
| 928 | @ press the "Apply" button. |
| 929 | style_finish_page("smtp"); |
| 930 | } |
| 931 | |
| 932 | #if LOCAL_INTERFACE |
| 933 | /* |
| 934 | ** State information for the server |
| 935 |
+57
-15
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1171,11 +1171,11 @@ | ||
| 1171 | 1171 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 1172 | 1172 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 1173 | 1173 | */ |
| 1174 | 1174 | #define SQLITE_VERSION "3.34.0" |
| 1175 | 1175 | #define SQLITE_VERSION_NUMBER 3034000 |
| 1176 | -#define SQLITE_SOURCE_ID "2020-10-19 20:49:54 75a0288871ccb2a69a636cbb328fe19045a0d0ef96a193ecd118b9a196784d2d" | |
| 1176 | +#define SQLITE_SOURCE_ID "2020-10-31 18:58:37 7d01e84dc49074e6364267eea9fd20d46a457d2498121a0f218fbf482692392d" | |
| 1177 | 1177 | |
| 1178 | 1178 | /* |
| 1179 | 1179 | ** CAPI3REF: Run-Time Library Version Numbers |
| 1180 | 1180 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 1181 | 1181 | ** |
| @@ -17621,10 +17621,11 @@ | ||
| 17621 | 17621 | ** Index.aiRowLogEst[] values */ |
| 17622 | 17622 | #define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */ |
| 17623 | 17623 | #define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */ |
| 17624 | 17624 | #define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */ |
| 17625 | 17625 | #define TF_Shadow 0x1000 /* True for a shadow table */ |
| 17626 | +#define TF_HasStat4 0x2000 /* STAT4 info available for this table */ | |
| 17626 | 17627 | |
| 17627 | 17628 | /* |
| 17628 | 17629 | ** Test to see whether or not a table is a virtual table. This is |
| 17629 | 17630 | ** done as a macro so that it will be optimized out when virtual |
| 17630 | 17631 | ** table support is omitted from the build. |
| @@ -27864,16 +27865,21 @@ | ||
| 27864 | 27865 | ** xRoundup. */ |
| 27865 | 27866 | nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); |
| 27866 | 27867 | if( nOld==nNew ){ |
| 27867 | 27868 | pNew = pOld; |
| 27868 | 27869 | }else if( sqlite3GlobalConfig.bMemstat ){ |
| 27870 | + sqlite3_int64 nUsed; | |
| 27869 | 27871 | sqlite3_mutex_enter(mem0.mutex); |
| 27870 | 27872 | sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); |
| 27871 | 27873 | nDiff = nNew - nOld; |
| 27872 | - if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= | |
| 27874 | + if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >= | |
| 27873 | 27875 | mem0.alarmThreshold-nDiff ){ |
| 27874 | 27876 | sqlite3MallocAlarm(nDiff); |
| 27877 | + if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){ | |
| 27878 | + sqlite3_mutex_leave(mem0.mutex); | |
| 27879 | + return 0; | |
| 27880 | + } | |
| 27875 | 27881 | } |
| 27876 | 27882 | pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
| 27877 | 27883 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 27878 | 27884 | if( pNew==0 && mem0.alarmThreshold>0 ){ |
| 27879 | 27885 | sqlite3MallocAlarm((int)nBytes); |
| @@ -48529,12 +48535,16 @@ | ||
| 48529 | 48535 | if( iDb<0 ){ |
| 48530 | 48536 | rc = SQLITE_ERROR; |
| 48531 | 48537 | goto end_deserialize; |
| 48532 | 48538 | } |
| 48533 | 48539 | zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); |
| 48534 | - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); | |
| 48535 | - sqlite3_free(zSql); | |
| 48540 | + if( zSql==0 ){ | |
| 48541 | + rc = SQLITE_NOMEM; | |
| 48542 | + }else{ | |
| 48543 | + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); | |
| 48544 | + sqlite3_free(zSql); | |
| 48545 | + } | |
| 48536 | 48546 | if( rc ) goto end_deserialize; |
| 48537 | 48547 | db->init.iDb = (u8)iDb; |
| 48538 | 48548 | db->init.reopenMemdb = 1; |
| 48539 | 48549 | rc = sqlite3_step(pStmt); |
| 48540 | 48550 | db->init.reopenMemdb = 0; |
| @@ -78362,10 +78372,11 @@ | ||
| 78362 | 78372 | */ |
| 78363 | 78373 | SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){ |
| 78364 | 78374 | int j; |
| 78365 | 78375 | sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); |
| 78366 | 78376 | for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j); |
| 78377 | + sqlite3MayAbort(p->pParse); | |
| 78367 | 78378 | } |
| 78368 | 78379 | |
| 78369 | 78380 | /* |
| 78370 | 78381 | ** Add an opcode that includes the p4 value as an integer. |
| 78371 | 78382 | */ |
| @@ -78590,11 +78601,11 @@ | ||
| 78590 | 78601 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 78591 | 78602 | int opcode = pOp->opcode; |
| 78592 | 78603 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 78593 | 78604 | || opcode==OP_VDestroy |
| 78594 | 78605 | || opcode==OP_VCreate |
| 78595 | - || (opcode==OP_ParseSchema && pOp->p4.z==0) | |
| 78606 | + || opcode==OP_ParseSchema | |
| 78596 | 78607 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 78597 | 78608 | && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) |
| 78598 | 78609 | ){ |
| 78599 | 78610 | hasAbort = 1; |
| 78600 | 78611 | break; |
| @@ -79408,11 +79419,11 @@ | ||
| 79408 | 79419 | sqlite3_context *pCtx = pOp->p4.pCtx; |
| 79409 | 79420 | if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){ |
| 79410 | 79421 | sqlite3_str_appendf(&x, "%d", v1); |
| 79411 | 79422 | }else if( pCtx->argc>1 ){ |
| 79412 | 79423 | sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1); |
| 79413 | - }else{ | |
| 79424 | + }else if( x.accError==0 ){ | |
| 79414 | 79425 | assert( x.nChar>2 ); |
| 79415 | 79426 | x.nChar -= 2; |
| 79416 | 79427 | ii++; |
| 79417 | 79428 | } |
| 79418 | 79429 | ii += 3; |
| @@ -107329,17 +107340,25 @@ | ||
| 107329 | 107340 | SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); |
| 107330 | 107341 | if( pSrc ){ |
| 107331 | 107342 | int i; |
| 107332 | 107343 | for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){ |
| 107333 | 107344 | struct SrcList_item *p = &pSrc->a[i]; |
| 107334 | - p->pTab = sqlite3LocateTableItem(pParse, 0, p); | |
| 107335 | 107345 | p->iCursor = pParse->nTab++; |
| 107336 | - if( p->pTab==0 ){ | |
| 107337 | - rc = SQLITE_ERROR; | |
| 107346 | + if( p->pSelect ){ | |
| 107347 | + sqlite3SelectPrep(pParse, p->pSelect, 0); | |
| 107348 | + sqlite3ExpandSubquery(pParse, p); | |
| 107349 | + assert( i>0 ); | |
| 107350 | + assert( pStep->pFrom->a[i-1].pSelect ); | |
| 107351 | + sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0); | |
| 107338 | 107352 | }else{ |
| 107339 | - p->pTab->nTabRef++; | |
| 107340 | - rc = sqlite3ViewGetColumnNames(pParse, p->pTab); | |
| 107353 | + p->pTab = sqlite3LocateTableItem(pParse, 0, p); | |
| 107354 | + if( p->pTab==0 ){ | |
| 107355 | + rc = SQLITE_ERROR; | |
| 107356 | + }else{ | |
| 107357 | + p->pTab->nTabRef++; | |
| 107358 | + rc = sqlite3ViewGetColumnNames(pParse, p->pTab); | |
| 107359 | + } | |
| 107341 | 107360 | } |
| 107342 | 107361 | } |
| 107343 | 107362 | sNC.pSrcList = pSrc; |
| 107344 | 107363 | if( rc==SQLITE_OK && pStep->pWhere ){ |
| 107345 | 107364 | rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); |
| @@ -107396,10 +107415,16 @@ | ||
| 107396 | 107415 | Upsert *pUpsert = pStep->pUpsert; |
| 107397 | 107416 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); |
| 107398 | 107417 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); |
| 107399 | 107418 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); |
| 107400 | 107419 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); |
| 107420 | + } | |
| 107421 | + if( pStep->pFrom ){ | |
| 107422 | + int i; | |
| 107423 | + for(i=0; i<pStep->pFrom->nSrc; i++){ | |
| 107424 | + sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect); | |
| 107425 | + } | |
| 107401 | 107426 | } |
| 107402 | 107427 | } |
| 107403 | 107428 | } |
| 107404 | 107429 | |
| 107405 | 107430 | /* |
| @@ -109655,10 +109680,11 @@ | ||
| 109655 | 109680 | sqlite3_finalize(pStmt); |
| 109656 | 109681 | return SQLITE_NOMEM_BKPT; |
| 109657 | 109682 | } |
| 109658 | 109683 | pSpace = (tRowcnt*)&pIdx->aSample[nSample]; |
| 109659 | 109684 | pIdx->aAvgEq = pSpace; pSpace += nIdxCol; |
| 109685 | + pIdx->pTable->tabFlags |= TF_HasStat4; | |
| 109660 | 109686 | for(i=0; i<nSample; i++){ |
| 109661 | 109687 | pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol; |
| 109662 | 109688 | pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; |
| 109663 | 109689 | pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; |
| 109664 | 109690 | } |
| @@ -149074,12 +149100,27 @@ | ||
| 149074 | 149100 | /* Integer primary key index */ |
| 149075 | 149101 | pNew->wsFlags = WHERE_IPK; |
| 149076 | 149102 | |
| 149077 | 149103 | /* Full table scan */ |
| 149078 | 149104 | pNew->iSortIdx = b ? iSortIdx : 0; |
| 149079 | - /* TUNING: Cost of full table scan is (N*3.0). */ | |
| 149105 | + /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an | |
| 149106 | + ** extra cost designed to discourage the use of full table scans, | |
| 149107 | + ** since index lookups have better worst-case performance if our | |
| 149108 | + ** stat guesses are wrong. Reduce the 3.0 penalty slightly | |
| 149109 | + ** (to 2.75) if we have valid STAT4 information for the table. | |
| 149110 | + ** At 2.75, a full table scan is preferred over using an index on | |
| 149111 | + ** a column with just two distinct values where each value has about | |
| 149112 | + ** an equal number of appearances. Without STAT4 data, we still want | |
| 149113 | + ** to use an index in that case, since the constraint might be for | |
| 149114 | + ** the scarcer of the two values, and in that case an index lookup is | |
| 149115 | + ** better. | |
| 149116 | + */ | |
| 149117 | +#ifdef SQLITE_ENABLE_STAT4 | |
| 149118 | + pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0); | |
| 149119 | +#else | |
| 149080 | 149120 | pNew->rRun = rSize + 16; |
| 149121 | +#endif | |
| 149081 | 149122 | ApplyCostMultiplier(pNew->rRun, pTab->costMult); |
| 149082 | 149123 | whereLoopOutputAdjust(pWC, pNew, rSize); |
| 149083 | 149124 | rc = whereLoopInsert(pBuilder, pNew); |
| 149084 | 149125 | pNew->nOut = rSize; |
| 149085 | 149126 | if( rc ) break; |
| @@ -226638,11 +226679,11 @@ | ||
| 226638 | 226679 | int nArg, /* Number of args */ |
| 226639 | 226680 | sqlite3_value **apUnused /* Function arguments */ |
| 226640 | 226681 | ){ |
| 226641 | 226682 | assert( nArg==0 ); |
| 226642 | 226683 | UNUSED_PARAM2(nArg, apUnused); |
| 226643 | - sqlite3_result_text(pCtx, "fts5: 2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5", -1, SQLITE_TRANSIENT); | |
| 226684 | + sqlite3_result_text(pCtx, "fts5: 2020-10-26 16:22:31 80eba105d6d1b49ba8ca2ad4e14ddec2de0bdc2f6686c2f8a1c1d24fc1fe846f", -1, SQLITE_TRANSIENT); | |
| 226644 | 226685 | } |
| 226645 | 226686 | |
| 226646 | 226687 | /* |
| 226647 | 226688 | ** Return true if zName is the extension on one of the shadow tables used |
| 226648 | 226689 | ** by this module. |
| @@ -230121,10 +230162,11 @@ | ||
| 230121 | 230162 | for(; i<128 && i<n; i++){ |
| 230122 | 230163 | aAscii[i] = (u8)bToken; |
| 230123 | 230164 | } |
| 230124 | 230165 | iTbl++; |
| 230125 | 230166 | } |
| 230167 | + aAscii[0] = 0; /* 0x00 is never a token character */ | |
| 230126 | 230168 | } |
| 230127 | 230169 | |
| 230128 | 230170 | /* |
| 230129 | 230171 | ** 2015 May 30 |
| 230130 | 230172 | ** |
| @@ -231560,12 +231602,12 @@ | ||
| 231560 | 231602 | } |
| 231561 | 231603 | #endif /* SQLITE_CORE */ |
| 231562 | 231604 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ |
| 231563 | 231605 | |
| 231564 | 231606 | /************** End of stmt.c ************************************************/ |
| 231565 | -#if __LINE__!=231565 | |
| 231607 | +#if __LINE__!=231607 | |
| 231566 | 231608 | #undef SQLITE_SOURCE_ID |
| 231567 | -#define SQLITE_SOURCE_ID "2020-10-19 20:49:54 75a0288871ccb2a69a636cbb328fe19045a0d0ef96a193ecd118b9a19678alt2" | |
| 231609 | +#define SQLITE_SOURCE_ID "2020-10-31 18:58:37 7d01e84dc49074e6364267eea9fd20d46a457d2498121a0f218fbf482692alt2" | |
| 231568 | 231610 | #endif |
| 231569 | 231611 | /* Return the source-id for this library */ |
| 231570 | 231612 | SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
| 231571 | 231613 | /************************** End of sqlite3.c ******************************/ |
| 231572 | 231614 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1171,11 +1171,11 @@ | |
| 1171 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 1172 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 1173 | */ |
| 1174 | #define SQLITE_VERSION "3.34.0" |
| 1175 | #define SQLITE_VERSION_NUMBER 3034000 |
| 1176 | #define SQLITE_SOURCE_ID "2020-10-19 20:49:54 75a0288871ccb2a69a636cbb328fe19045a0d0ef96a193ecd118b9a196784d2d" |
| 1177 | |
| 1178 | /* |
| 1179 | ** CAPI3REF: Run-Time Library Version Numbers |
| 1180 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 1181 | ** |
| @@ -17621,10 +17621,11 @@ | |
| 17621 | ** Index.aiRowLogEst[] values */ |
| 17622 | #define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */ |
| 17623 | #define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */ |
| 17624 | #define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */ |
| 17625 | #define TF_Shadow 0x1000 /* True for a shadow table */ |
| 17626 | |
| 17627 | /* |
| 17628 | ** Test to see whether or not a table is a virtual table. This is |
| 17629 | ** done as a macro so that it will be optimized out when virtual |
| 17630 | ** table support is omitted from the build. |
| @@ -27864,16 +27865,21 @@ | |
| 27864 | ** xRoundup. */ |
| 27865 | nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); |
| 27866 | if( nOld==nNew ){ |
| 27867 | pNew = pOld; |
| 27868 | }else if( sqlite3GlobalConfig.bMemstat ){ |
| 27869 | sqlite3_mutex_enter(mem0.mutex); |
| 27870 | sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); |
| 27871 | nDiff = nNew - nOld; |
| 27872 | if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= |
| 27873 | mem0.alarmThreshold-nDiff ){ |
| 27874 | sqlite3MallocAlarm(nDiff); |
| 27875 | } |
| 27876 | pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
| 27877 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 27878 | if( pNew==0 && mem0.alarmThreshold>0 ){ |
| 27879 | sqlite3MallocAlarm((int)nBytes); |
| @@ -48529,12 +48535,16 @@ | |
| 48529 | if( iDb<0 ){ |
| 48530 | rc = SQLITE_ERROR; |
| 48531 | goto end_deserialize; |
| 48532 | } |
| 48533 | zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); |
| 48534 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 48535 | sqlite3_free(zSql); |
| 48536 | if( rc ) goto end_deserialize; |
| 48537 | db->init.iDb = (u8)iDb; |
| 48538 | db->init.reopenMemdb = 1; |
| 48539 | rc = sqlite3_step(pStmt); |
| 48540 | db->init.reopenMemdb = 0; |
| @@ -78362,10 +78372,11 @@ | |
| 78362 | */ |
| 78363 | SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){ |
| 78364 | int j; |
| 78365 | sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); |
| 78366 | for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j); |
| 78367 | } |
| 78368 | |
| 78369 | /* |
| 78370 | ** Add an opcode that includes the p4 value as an integer. |
| 78371 | */ |
| @@ -78590,11 +78601,11 @@ | |
| 78590 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 78591 | int opcode = pOp->opcode; |
| 78592 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 78593 | || opcode==OP_VDestroy |
| 78594 | || opcode==OP_VCreate |
| 78595 | || (opcode==OP_ParseSchema && pOp->p4.z==0) |
| 78596 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 78597 | && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) |
| 78598 | ){ |
| 78599 | hasAbort = 1; |
| 78600 | break; |
| @@ -79408,11 +79419,11 @@ | |
| 79408 | sqlite3_context *pCtx = pOp->p4.pCtx; |
| 79409 | if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){ |
| 79410 | sqlite3_str_appendf(&x, "%d", v1); |
| 79411 | }else if( pCtx->argc>1 ){ |
| 79412 | sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1); |
| 79413 | }else{ |
| 79414 | assert( x.nChar>2 ); |
| 79415 | x.nChar -= 2; |
| 79416 | ii++; |
| 79417 | } |
| 79418 | ii += 3; |
| @@ -107329,17 +107340,25 @@ | |
| 107329 | SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); |
| 107330 | if( pSrc ){ |
| 107331 | int i; |
| 107332 | for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){ |
| 107333 | struct SrcList_item *p = &pSrc->a[i]; |
| 107334 | p->pTab = sqlite3LocateTableItem(pParse, 0, p); |
| 107335 | p->iCursor = pParse->nTab++; |
| 107336 | if( p->pTab==0 ){ |
| 107337 | rc = SQLITE_ERROR; |
| 107338 | }else{ |
| 107339 | p->pTab->nTabRef++; |
| 107340 | rc = sqlite3ViewGetColumnNames(pParse, p->pTab); |
| 107341 | } |
| 107342 | } |
| 107343 | sNC.pSrcList = pSrc; |
| 107344 | if( rc==SQLITE_OK && pStep->pWhere ){ |
| 107345 | rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); |
| @@ -107396,10 +107415,16 @@ | |
| 107396 | Upsert *pUpsert = pStep->pUpsert; |
| 107397 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); |
| 107398 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); |
| 107399 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); |
| 107400 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); |
| 107401 | } |
| 107402 | } |
| 107403 | } |
| 107404 | |
| 107405 | /* |
| @@ -109655,10 +109680,11 @@ | |
| 109655 | sqlite3_finalize(pStmt); |
| 109656 | return SQLITE_NOMEM_BKPT; |
| 109657 | } |
| 109658 | pSpace = (tRowcnt*)&pIdx->aSample[nSample]; |
| 109659 | pIdx->aAvgEq = pSpace; pSpace += nIdxCol; |
| 109660 | for(i=0; i<nSample; i++){ |
| 109661 | pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol; |
| 109662 | pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; |
| 109663 | pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; |
| 109664 | } |
| @@ -149074,12 +149100,27 @@ | |
| 149074 | /* Integer primary key index */ |
| 149075 | pNew->wsFlags = WHERE_IPK; |
| 149076 | |
| 149077 | /* Full table scan */ |
| 149078 | pNew->iSortIdx = b ? iSortIdx : 0; |
| 149079 | /* TUNING: Cost of full table scan is (N*3.0). */ |
| 149080 | pNew->rRun = rSize + 16; |
| 149081 | ApplyCostMultiplier(pNew->rRun, pTab->costMult); |
| 149082 | whereLoopOutputAdjust(pWC, pNew, rSize); |
| 149083 | rc = whereLoopInsert(pBuilder, pNew); |
| 149084 | pNew->nOut = rSize; |
| 149085 | if( rc ) break; |
| @@ -226638,11 +226679,11 @@ | |
| 226638 | int nArg, /* Number of args */ |
| 226639 | sqlite3_value **apUnused /* Function arguments */ |
| 226640 | ){ |
| 226641 | assert( nArg==0 ); |
| 226642 | UNUSED_PARAM2(nArg, apUnused); |
| 226643 | sqlite3_result_text(pCtx, "fts5: 2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5", -1, SQLITE_TRANSIENT); |
| 226644 | } |
| 226645 | |
| 226646 | /* |
| 226647 | ** Return true if zName is the extension on one of the shadow tables used |
| 226648 | ** by this module. |
| @@ -230121,10 +230162,11 @@ | |
| 230121 | for(; i<128 && i<n; i++){ |
| 230122 | aAscii[i] = (u8)bToken; |
| 230123 | } |
| 230124 | iTbl++; |
| 230125 | } |
| 230126 | } |
| 230127 | |
| 230128 | /* |
| 230129 | ** 2015 May 30 |
| 230130 | ** |
| @@ -231560,12 +231602,12 @@ | |
| 231560 | } |
| 231561 | #endif /* SQLITE_CORE */ |
| 231562 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ |
| 231563 | |
| 231564 | /************** End of stmt.c ************************************************/ |
| 231565 | #if __LINE__!=231565 |
| 231566 | #undef SQLITE_SOURCE_ID |
| 231567 | #define SQLITE_SOURCE_ID "2020-10-19 20:49:54 75a0288871ccb2a69a636cbb328fe19045a0d0ef96a193ecd118b9a19678alt2" |
| 231568 | #endif |
| 231569 | /* Return the source-id for this library */ |
| 231570 | SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
| 231571 | /************************** End of sqlite3.c ******************************/ |
| 231572 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1171,11 +1171,11 @@ | |
| 1171 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 1172 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 1173 | */ |
| 1174 | #define SQLITE_VERSION "3.34.0" |
| 1175 | #define SQLITE_VERSION_NUMBER 3034000 |
| 1176 | #define SQLITE_SOURCE_ID "2020-10-31 18:58:37 7d01e84dc49074e6364267eea9fd20d46a457d2498121a0f218fbf482692392d" |
| 1177 | |
| 1178 | /* |
| 1179 | ** CAPI3REF: Run-Time Library Version Numbers |
| 1180 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 1181 | ** |
| @@ -17621,10 +17621,11 @@ | |
| 17621 | ** Index.aiRowLogEst[] values */ |
| 17622 | #define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */ |
| 17623 | #define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */ |
| 17624 | #define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */ |
| 17625 | #define TF_Shadow 0x1000 /* True for a shadow table */ |
| 17626 | #define TF_HasStat4 0x2000 /* STAT4 info available for this table */ |
| 17627 | |
| 17628 | /* |
| 17629 | ** Test to see whether or not a table is a virtual table. This is |
| 17630 | ** done as a macro so that it will be optimized out when virtual |
| 17631 | ** table support is omitted from the build. |
| @@ -27864,16 +27865,21 @@ | |
| 27865 | ** xRoundup. */ |
| 27866 | nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes); |
| 27867 | if( nOld==nNew ){ |
| 27868 | pNew = pOld; |
| 27869 | }else if( sqlite3GlobalConfig.bMemstat ){ |
| 27870 | sqlite3_int64 nUsed; |
| 27871 | sqlite3_mutex_enter(mem0.mutex); |
| 27872 | sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); |
| 27873 | nDiff = nNew - nOld; |
| 27874 | if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >= |
| 27875 | mem0.alarmThreshold-nDiff ){ |
| 27876 | sqlite3MallocAlarm(nDiff); |
| 27877 | if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){ |
| 27878 | sqlite3_mutex_leave(mem0.mutex); |
| 27879 | return 0; |
| 27880 | } |
| 27881 | } |
| 27882 | pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
| 27883 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 27884 | if( pNew==0 && mem0.alarmThreshold>0 ){ |
| 27885 | sqlite3MallocAlarm((int)nBytes); |
| @@ -48529,12 +48535,16 @@ | |
| 48535 | if( iDb<0 ){ |
| 48536 | rc = SQLITE_ERROR; |
| 48537 | goto end_deserialize; |
| 48538 | } |
| 48539 | zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); |
| 48540 | if( zSql==0 ){ |
| 48541 | rc = SQLITE_NOMEM; |
| 48542 | }else{ |
| 48543 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 48544 | sqlite3_free(zSql); |
| 48545 | } |
| 48546 | if( rc ) goto end_deserialize; |
| 48547 | db->init.iDb = (u8)iDb; |
| 48548 | db->init.reopenMemdb = 1; |
| 48549 | rc = sqlite3_step(pStmt); |
| 48550 | db->init.reopenMemdb = 0; |
| @@ -78362,10 +78372,11 @@ | |
| 78372 | */ |
| 78373 | SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){ |
| 78374 | int j; |
| 78375 | sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); |
| 78376 | for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j); |
| 78377 | sqlite3MayAbort(p->pParse); |
| 78378 | } |
| 78379 | |
| 78380 | /* |
| 78381 | ** Add an opcode that includes the p4 value as an integer. |
| 78382 | */ |
| @@ -78590,11 +78601,11 @@ | |
| 78601 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 78602 | int opcode = pOp->opcode; |
| 78603 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 78604 | || opcode==OP_VDestroy |
| 78605 | || opcode==OP_VCreate |
| 78606 | || opcode==OP_ParseSchema |
| 78607 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 78608 | && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) |
| 78609 | ){ |
| 78610 | hasAbort = 1; |
| 78611 | break; |
| @@ -79408,11 +79419,11 @@ | |
| 79419 | sqlite3_context *pCtx = pOp->p4.pCtx; |
| 79420 | if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){ |
| 79421 | sqlite3_str_appendf(&x, "%d", v1); |
| 79422 | }else if( pCtx->argc>1 ){ |
| 79423 | sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1); |
| 79424 | }else if( x.accError==0 ){ |
| 79425 | assert( x.nChar>2 ); |
| 79426 | x.nChar -= 2; |
| 79427 | ii++; |
| 79428 | } |
| 79429 | ii += 3; |
| @@ -107329,17 +107340,25 @@ | |
| 107340 | SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); |
| 107341 | if( pSrc ){ |
| 107342 | int i; |
| 107343 | for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){ |
| 107344 | struct SrcList_item *p = &pSrc->a[i]; |
| 107345 | p->iCursor = pParse->nTab++; |
| 107346 | if( p->pSelect ){ |
| 107347 | sqlite3SelectPrep(pParse, p->pSelect, 0); |
| 107348 | sqlite3ExpandSubquery(pParse, p); |
| 107349 | assert( i>0 ); |
| 107350 | assert( pStep->pFrom->a[i-1].pSelect ); |
| 107351 | sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0); |
| 107352 | }else{ |
| 107353 | p->pTab = sqlite3LocateTableItem(pParse, 0, p); |
| 107354 | if( p->pTab==0 ){ |
| 107355 | rc = SQLITE_ERROR; |
| 107356 | }else{ |
| 107357 | p->pTab->nTabRef++; |
| 107358 | rc = sqlite3ViewGetColumnNames(pParse, p->pTab); |
| 107359 | } |
| 107360 | } |
| 107361 | } |
| 107362 | sNC.pSrcList = pSrc; |
| 107363 | if( rc==SQLITE_OK && pStep->pWhere ){ |
| 107364 | rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); |
| @@ -107396,10 +107415,16 @@ | |
| 107415 | Upsert *pUpsert = pStep->pUpsert; |
| 107416 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); |
| 107417 | sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); |
| 107418 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); |
| 107419 | sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); |
| 107420 | } |
| 107421 | if( pStep->pFrom ){ |
| 107422 | int i; |
| 107423 | for(i=0; i<pStep->pFrom->nSrc; i++){ |
| 107424 | sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect); |
| 107425 | } |
| 107426 | } |
| 107427 | } |
| 107428 | } |
| 107429 | |
| 107430 | /* |
| @@ -109655,10 +109680,11 @@ | |
| 109680 | sqlite3_finalize(pStmt); |
| 109681 | return SQLITE_NOMEM_BKPT; |
| 109682 | } |
| 109683 | pSpace = (tRowcnt*)&pIdx->aSample[nSample]; |
| 109684 | pIdx->aAvgEq = pSpace; pSpace += nIdxCol; |
| 109685 | pIdx->pTable->tabFlags |= TF_HasStat4; |
| 109686 | for(i=0; i<nSample; i++){ |
| 109687 | pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol; |
| 109688 | pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; |
| 109689 | pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; |
| 109690 | } |
| @@ -149074,12 +149100,27 @@ | |
| 149100 | /* Integer primary key index */ |
| 149101 | pNew->wsFlags = WHERE_IPK; |
| 149102 | |
| 149103 | /* Full table scan */ |
| 149104 | pNew->iSortIdx = b ? iSortIdx : 0; |
| 149105 | /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an |
| 149106 | ** extra cost designed to discourage the use of full table scans, |
| 149107 | ** since index lookups have better worst-case performance if our |
| 149108 | ** stat guesses are wrong. Reduce the 3.0 penalty slightly |
| 149109 | ** (to 2.75) if we have valid STAT4 information for the table. |
| 149110 | ** At 2.75, a full table scan is preferred over using an index on |
| 149111 | ** a column with just two distinct values where each value has about |
| 149112 | ** an equal number of appearances. Without STAT4 data, we still want |
| 149113 | ** to use an index in that case, since the constraint might be for |
| 149114 | ** the scarcer of the two values, and in that case an index lookup is |
| 149115 | ** better. |
| 149116 | */ |
| 149117 | #ifdef SQLITE_ENABLE_STAT4 |
| 149118 | pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0); |
| 149119 | #else |
| 149120 | pNew->rRun = rSize + 16; |
| 149121 | #endif |
| 149122 | ApplyCostMultiplier(pNew->rRun, pTab->costMult); |
| 149123 | whereLoopOutputAdjust(pWC, pNew, rSize); |
| 149124 | rc = whereLoopInsert(pBuilder, pNew); |
| 149125 | pNew->nOut = rSize; |
| 149126 | if( rc ) break; |
| @@ -226638,11 +226679,11 @@ | |
| 226679 | int nArg, /* Number of args */ |
| 226680 | sqlite3_value **apUnused /* Function arguments */ |
| 226681 | ){ |
| 226682 | assert( nArg==0 ); |
| 226683 | UNUSED_PARAM2(nArg, apUnused); |
| 226684 | sqlite3_result_text(pCtx, "fts5: 2020-10-26 16:22:31 80eba105d6d1b49ba8ca2ad4e14ddec2de0bdc2f6686c2f8a1c1d24fc1fe846f", -1, SQLITE_TRANSIENT); |
| 226685 | } |
| 226686 | |
| 226687 | /* |
| 226688 | ** Return true if zName is the extension on one of the shadow tables used |
| 226689 | ** by this module. |
| @@ -230121,10 +230162,11 @@ | |
| 230162 | for(; i<128 && i<n; i++){ |
| 230163 | aAscii[i] = (u8)bToken; |
| 230164 | } |
| 230165 | iTbl++; |
| 230166 | } |
| 230167 | aAscii[0] = 0; /* 0x00 is never a token character */ |
| 230168 | } |
| 230169 | |
| 230170 | /* |
| 230171 | ** 2015 May 30 |
| 230172 | ** |
| @@ -231560,12 +231602,12 @@ | |
| 231602 | } |
| 231603 | #endif /* SQLITE_CORE */ |
| 231604 | #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ |
| 231605 | |
| 231606 | /************** End of stmt.c ************************************************/ |
| 231607 | #if __LINE__!=231607 |
| 231608 | #undef SQLITE_SOURCE_ID |
| 231609 | #define SQLITE_SOURCE_ID "2020-10-31 18:58:37 7d01e84dc49074e6364267eea9fd20d46a457d2498121a0f218fbf482692alt2" |
| 231610 | #endif |
| 231611 | /* Return the source-id for this library */ |
| 231612 | SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } |
| 231613 | /************************** End of sqlite3.c ******************************/ |
| 231614 |
+1
-1
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -123,11 +123,11 @@ | ||
| 123 | 123 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 124 | 124 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 125 | 125 | */ |
| 126 | 126 | #define SQLITE_VERSION "3.34.0" |
| 127 | 127 | #define SQLITE_VERSION_NUMBER 3034000 |
| 128 | -#define SQLITE_SOURCE_ID "2020-10-19 20:49:54 75a0288871ccb2a69a636cbb328fe19045a0d0ef96a193ecd118b9a196784d2d" | |
| 128 | +#define SQLITE_SOURCE_ID "2020-10-31 18:58:37 7d01e84dc49074e6364267eea9fd20d46a457d2498121a0f218fbf482692392d" | |
| 129 | 129 | |
| 130 | 130 | /* |
| 131 | 131 | ** CAPI3REF: Run-Time Library Version Numbers |
| 132 | 132 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 133 | 133 | ** |
| 134 | 134 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -123,11 +123,11 @@ | |
| 123 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 124 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 125 | */ |
| 126 | #define SQLITE_VERSION "3.34.0" |
| 127 | #define SQLITE_VERSION_NUMBER 3034000 |
| 128 | #define SQLITE_SOURCE_ID "2020-10-19 20:49:54 75a0288871ccb2a69a636cbb328fe19045a0d0ef96a193ecd118b9a196784d2d" |
| 129 | |
| 130 | /* |
| 131 | ** CAPI3REF: Run-Time Library Version Numbers |
| 132 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 133 | ** |
| 134 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -123,11 +123,11 @@ | |
| 123 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 124 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 125 | */ |
| 126 | #define SQLITE_VERSION "3.34.0" |
| 127 | #define SQLITE_VERSION_NUMBER 3034000 |
| 128 | #define SQLITE_SOURCE_ID "2020-10-31 18:58:37 7d01e84dc49074e6364267eea9fd20d46a457d2498121a0f218fbf482692392d" |
| 129 | |
| 130 | /* |
| 131 | ** CAPI3REF: Run-Time Library Version Numbers |
| 132 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 133 | ** |
| 134 |
+7
-7
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -288,11 +288,11 @@ | ||
| 288 | 288 | if( g.perm.Admin && alert_enabled() ){ |
| 289 | 289 | stats_for_email(); |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | 292 | @ </table> |
| 293 | - style_footer(); | |
| 293 | + style_finish_page("stat"); | |
| 294 | 294 | } |
| 295 | 295 | |
| 296 | 296 | /* |
| 297 | 297 | ** COMMAND: dbstat |
| 298 | 298 | ** |
| @@ -507,11 +507,11 @@ | ||
| 507 | 507 | }else{ |
| 508 | 508 | @ <p>%h(zRemote)</p> |
| 509 | 509 | } |
| 510 | 510 | @ </div> |
| 511 | 511 | } |
| 512 | - style_footer(); | |
| 512 | + style_finish_page("stat"); | |
| 513 | 513 | } |
| 514 | 514 | |
| 515 | 515 | /* |
| 516 | 516 | ** WEBPAGE: repo_schema |
| 517 | 517 | ** |
| @@ -565,11 +565,11 @@ | ||
| 565 | 565 | db_finalize(&q); |
| 566 | 566 | }else{ |
| 567 | 567 | style_submenu_element("Stat1","repo_stat1"); |
| 568 | 568 | } |
| 569 | 569 | } |
| 570 | - style_footer(); | |
| 570 | + style_finish_page("stat"); | |
| 571 | 571 | } |
| 572 | 572 | |
| 573 | 573 | /* |
| 574 | 574 | ** WEBPAGE: repo_stat1 |
| 575 | 575 | ** |
| @@ -597,11 +597,11 @@ | ||
| 597 | 597 | @ INSERT INTO sqlite_stat1 VALUES('%z(zUrl)%h(zTab)</a>','%h(zIdx)','%h(zStat)'); |
| 598 | 598 | } |
| 599 | 599 | @ </pre> |
| 600 | 600 | db_finalize(&q); |
| 601 | 601 | } |
| 602 | - style_footer(); | |
| 602 | + style_finish_page("stat"); | |
| 603 | 603 | } |
| 604 | 604 | |
| 605 | 605 | /* |
| 606 | 606 | ** WEBPAGE: repo-tabsize |
| 607 | 607 | ** |
| @@ -669,11 +669,11 @@ | ||
| 669 | 669 | @ <h2>%h(file_tail(g.zLocalDbName)) Size: %s(zBuf)</h2> |
| 670 | 670 | @ <center><svg width='800' height='500'> |
| 671 | 671 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 672 | 672 | @ </svg></center> |
| 673 | 673 | } |
| 674 | - style_footer(); | |
| 674 | + style_finish_page("stat"); | |
| 675 | 675 | } |
| 676 | 676 | |
| 677 | 677 | /* |
| 678 | 678 | ** Gather statistics on artifact types, counts, and sizes. |
| 679 | 679 | ** |
| @@ -810,11 +810,11 @@ | ||
| 810 | 810 | sumCmpr = db_column_int64(&q, 4); |
| 811 | 811 | sumExp = db_column_int64(&q, 5); |
| 812 | 812 | db_finalize(&q); |
| 813 | 813 | if( nTotal==0 ){ |
| 814 | 814 | @ No artifacts in this repository! |
| 815 | - style_footer(); | |
| 815 | + style_finish_page("stat"); | |
| 816 | 816 | return; |
| 817 | 817 | } |
| 818 | 818 | avgCmpr = (double)sumCmpr/nTotal; |
| 819 | 819 | avgExp = (double)sumExp/nTotal; |
| 820 | 820 | |
| @@ -955,7 +955,7 @@ | ||
| 955 | 955 | } |
| 956 | 956 | @ </tbody></table></div> |
| 957 | 957 | db_finalize(&q); |
| 958 | 958 | } |
| 959 | 959 | style_table_sorter(); |
| 960 | - style_footer(); | |
| 960 | + style_finish_page("stat"); | |
| 961 | 961 | } |
| 962 | 962 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -288,11 +288,11 @@ | |
| 288 | if( g.perm.Admin && alert_enabled() ){ |
| 289 | stats_for_email(); |
| 290 | } |
| 291 | |
| 292 | @ </table> |
| 293 | style_footer(); |
| 294 | } |
| 295 | |
| 296 | /* |
| 297 | ** COMMAND: dbstat |
| 298 | ** |
| @@ -507,11 +507,11 @@ | |
| 507 | }else{ |
| 508 | @ <p>%h(zRemote)</p> |
| 509 | } |
| 510 | @ </div> |
| 511 | } |
| 512 | style_footer(); |
| 513 | } |
| 514 | |
| 515 | /* |
| 516 | ** WEBPAGE: repo_schema |
| 517 | ** |
| @@ -565,11 +565,11 @@ | |
| 565 | db_finalize(&q); |
| 566 | }else{ |
| 567 | style_submenu_element("Stat1","repo_stat1"); |
| 568 | } |
| 569 | } |
| 570 | style_footer(); |
| 571 | } |
| 572 | |
| 573 | /* |
| 574 | ** WEBPAGE: repo_stat1 |
| 575 | ** |
| @@ -597,11 +597,11 @@ | |
| 597 | @ INSERT INTO sqlite_stat1 VALUES('%z(zUrl)%h(zTab)</a>','%h(zIdx)','%h(zStat)'); |
| 598 | } |
| 599 | @ </pre> |
| 600 | db_finalize(&q); |
| 601 | } |
| 602 | style_footer(); |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | ** WEBPAGE: repo-tabsize |
| 607 | ** |
| @@ -669,11 +669,11 @@ | |
| 669 | @ <h2>%h(file_tail(g.zLocalDbName)) Size: %s(zBuf)</h2> |
| 670 | @ <center><svg width='800' height='500'> |
| 671 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 672 | @ </svg></center> |
| 673 | } |
| 674 | style_footer(); |
| 675 | } |
| 676 | |
| 677 | /* |
| 678 | ** Gather statistics on artifact types, counts, and sizes. |
| 679 | ** |
| @@ -810,11 +810,11 @@ | |
| 810 | sumCmpr = db_column_int64(&q, 4); |
| 811 | sumExp = db_column_int64(&q, 5); |
| 812 | db_finalize(&q); |
| 813 | if( nTotal==0 ){ |
| 814 | @ No artifacts in this repository! |
| 815 | style_footer(); |
| 816 | return; |
| 817 | } |
| 818 | avgCmpr = (double)sumCmpr/nTotal; |
| 819 | avgExp = (double)sumExp/nTotal; |
| 820 | |
| @@ -955,7 +955,7 @@ | |
| 955 | } |
| 956 | @ </tbody></table></div> |
| 957 | db_finalize(&q); |
| 958 | } |
| 959 | style_table_sorter(); |
| 960 | style_footer(); |
| 961 | } |
| 962 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -288,11 +288,11 @@ | |
| 288 | if( g.perm.Admin && alert_enabled() ){ |
| 289 | stats_for_email(); |
| 290 | } |
| 291 | |
| 292 | @ </table> |
| 293 | style_finish_page("stat"); |
| 294 | } |
| 295 | |
| 296 | /* |
| 297 | ** COMMAND: dbstat |
| 298 | ** |
| @@ -507,11 +507,11 @@ | |
| 507 | }else{ |
| 508 | @ <p>%h(zRemote)</p> |
| 509 | } |
| 510 | @ </div> |
| 511 | } |
| 512 | style_finish_page("stat"); |
| 513 | } |
| 514 | |
| 515 | /* |
| 516 | ** WEBPAGE: repo_schema |
| 517 | ** |
| @@ -565,11 +565,11 @@ | |
| 565 | db_finalize(&q); |
| 566 | }else{ |
| 567 | style_submenu_element("Stat1","repo_stat1"); |
| 568 | } |
| 569 | } |
| 570 | style_finish_page("stat"); |
| 571 | } |
| 572 | |
| 573 | /* |
| 574 | ** WEBPAGE: repo_stat1 |
| 575 | ** |
| @@ -597,11 +597,11 @@ | |
| 597 | @ INSERT INTO sqlite_stat1 VALUES('%z(zUrl)%h(zTab)</a>','%h(zIdx)','%h(zStat)'); |
| 598 | } |
| 599 | @ </pre> |
| 600 | db_finalize(&q); |
| 601 | } |
| 602 | style_finish_page("stat"); |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | ** WEBPAGE: repo-tabsize |
| 607 | ** |
| @@ -669,11 +669,11 @@ | |
| 669 | @ <h2>%h(file_tail(g.zLocalDbName)) Size: %s(zBuf)</h2> |
| 670 | @ <center><svg width='800' height='500'> |
| 671 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 672 | @ </svg></center> |
| 673 | } |
| 674 | style_finish_page("stat"); |
| 675 | } |
| 676 | |
| 677 | /* |
| 678 | ** Gather statistics on artifact types, counts, and sizes. |
| 679 | ** |
| @@ -810,11 +810,11 @@ | |
| 810 | sumCmpr = db_column_int64(&q, 4); |
| 811 | sumExp = db_column_int64(&q, 5); |
| 812 | db_finalize(&q); |
| 813 | if( nTotal==0 ){ |
| 814 | @ No artifacts in this repository! |
| 815 | style_finish_page("stat"); |
| 816 | return; |
| 817 | } |
| 818 | avgCmpr = (double)sumCmpr/nTotal; |
| 819 | avgExp = (double)sumExp/nTotal; |
| 820 | |
| @@ -955,7 +955,7 @@ | |
| 955 | } |
| 956 | @ </tbody></table></div> |
| 957 | db_finalize(&q); |
| 958 | } |
| 959 | style_table_sorter(); |
| 960 | style_finish_page("stat"); |
| 961 | } |
| 962 |
+1
-1
| --- src/statrep.c | ||
| +++ src/statrep.c | ||
| @@ -825,7 +825,7 @@ | ||
| 825 | 825 | break; |
| 826 | 826 | case RPT_LASTCHNG: |
| 827 | 827 | stats_report_last_change(); |
| 828 | 828 | break; |
| 829 | 829 | } |
| 830 | - style_footer(); | |
| 830 | + style_finish_page("reports"); | |
| 831 | 831 | } |
| 832 | 832 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -825,7 +825,7 @@ | |
| 825 | break; |
| 826 | case RPT_LASTCHNG: |
| 827 | stats_report_last_change(); |
| 828 | break; |
| 829 | } |
| 830 | style_footer(); |
| 831 | } |
| 832 |
| --- src/statrep.c | |
| +++ src/statrep.c | |
| @@ -825,7 +825,7 @@ | |
| 825 | break; |
| 826 | case RPT_LASTCHNG: |
| 827 | stats_report_last_change(); |
| 828 | break; |
| 829 | } |
| 830 | style_finish_page("reports"); |
| 831 | } |
| 832 |
+26
-17
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -736,13 +736,28 @@ | ||
| 736 | 736 | @ </script> |
| 737 | 737 | builtin_fulfill_js_requests(); |
| 738 | 738 | } |
| 739 | 739 | |
| 740 | 740 | /* |
| 741 | -** Draw the footer at the bottom of the page. | |
| 741 | +** Invoke this routine after all of the content for a webpage has been | |
| 742 | +** generated. This routine should be called once for every webpage, at | |
| 743 | +** or near the end of page generation. This routine does the following: | |
| 744 | +** | |
| 745 | +** * Populates the header of the page, including setting up appropriate | |
| 746 | +** submenu elements. The header generation is deferred until this point | |
| 747 | +** so that we know that all style_submenu_element() and similar have | |
| 748 | +** been received. | |
| 749 | +** | |
| 750 | +** * Finalizes the page content. | |
| 751 | +** | |
| 752 | +** * Appends the footer. | |
| 753 | +** | |
| 754 | +** The zPageType argument is a class name inserted in the <div> that | |
| 755 | +** surrounds the page content. CSS can use this to have different styles | |
| 756 | +** according to the page type. | |
| 742 | 757 | */ |
| 743 | -void style_footer(void){ | |
| 758 | +void style_finish_page(const char* zPageType){ | |
| 744 | 759 | const char *zFooter; |
| 745 | 760 | const char *zAd = 0; |
| 746 | 761 | unsigned int mAdFlags = 0; |
| 747 | 762 | |
| 748 | 763 | if( !headerHasBeenGenerated ) return; |
| @@ -864,31 +879,25 @@ | ||
| 864 | 879 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| 865 | 880 | @ <div class="content adunit_right_container"> |
| 866 | 881 | @ <div class="adunit_right"> |
| 867 | 882 | cgi_append_content(zAd, -1); |
| 868 | 883 | @ </div> |
| 869 | - }else{ | |
| 870 | - if( zAd ){ | |
| 871 | - @ <div class="adunit_banner"> | |
| 872 | - cgi_append_content(zAd, -1); | |
| 873 | - @ </div> | |
| 874 | - } | |
| 875 | - @ <div class="content"><span id="debugMsg"></span> | |
| 876 | - } | |
| 884 | + }else if( zAd ){ | |
| 885 | + @ <div class="adunit_banner"> | |
| 886 | + cgi_append_content(zAd, -1); | |
| 887 | + @ </div> | |
| 888 | + } | |
| 889 | + | |
| 890 | + @ <div class="content %s(zPageType)"><span id="debugMsg"></span> | |
| 877 | 891 | cgi_destination(CGI_BODY); |
| 878 | 892 | |
| 879 | 893 | if( sideboxUsed ){ |
| 880 | - /* Put the footer at the bottom of the page. | |
| 881 | - ** the additional clear/both is needed to extend the content | |
| 882 | - ** part to the end of an optional sidebox. | |
| 883 | - */ | |
| 884 | 894 | @ <div class="endContent"></div> |
| 885 | 895 | } |
| 886 | 896 | @ </div> |
| 887 | 897 | |
| 888 | - | |
| 889 | - | |
| 898 | + /* Put the footer at the bottom of the page. */ | |
| 890 | 899 | zFooter = skin_get("footer"); |
| 891 | 900 | if( sqlite3_strlike("%</body>%", zFooter, 0)==0 ){ |
| 892 | 901 | style_load_all_js_files(); |
| 893 | 902 | } |
| 894 | 903 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| @@ -1195,11 +1204,11 @@ | ||
| 1195 | 1204 | @ <pre> |
| 1196 | 1205 | @ %h(blob_str(&g.httpHeader)) |
| 1197 | 1206 | @ </pre> |
| 1198 | 1207 | } |
| 1199 | 1208 | } |
| 1200 | - style_footer(); | |
| 1209 | + style_finish_page("error"); | |
| 1201 | 1210 | if( zErr ){ |
| 1202 | 1211 | cgi_reply(); |
| 1203 | 1212 | fossil_exit(1); |
| 1204 | 1213 | } |
| 1205 | 1214 | } |
| 1206 | 1215 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -736,13 +736,28 @@ | |
| 736 | @ </script> |
| 737 | builtin_fulfill_js_requests(); |
| 738 | } |
| 739 | |
| 740 | /* |
| 741 | ** Draw the footer at the bottom of the page. |
| 742 | */ |
| 743 | void style_footer(void){ |
| 744 | const char *zFooter; |
| 745 | const char *zAd = 0; |
| 746 | unsigned int mAdFlags = 0; |
| 747 | |
| 748 | if( !headerHasBeenGenerated ) return; |
| @@ -864,31 +879,25 @@ | |
| 864 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| 865 | @ <div class="content adunit_right_container"> |
| 866 | @ <div class="adunit_right"> |
| 867 | cgi_append_content(zAd, -1); |
| 868 | @ </div> |
| 869 | }else{ |
| 870 | if( zAd ){ |
| 871 | @ <div class="adunit_banner"> |
| 872 | cgi_append_content(zAd, -1); |
| 873 | @ </div> |
| 874 | } |
| 875 | @ <div class="content"><span id="debugMsg"></span> |
| 876 | } |
| 877 | cgi_destination(CGI_BODY); |
| 878 | |
| 879 | if( sideboxUsed ){ |
| 880 | /* Put the footer at the bottom of the page. |
| 881 | ** the additional clear/both is needed to extend the content |
| 882 | ** part to the end of an optional sidebox. |
| 883 | */ |
| 884 | @ <div class="endContent"></div> |
| 885 | } |
| 886 | @ </div> |
| 887 | |
| 888 | |
| 889 | |
| 890 | zFooter = skin_get("footer"); |
| 891 | if( sqlite3_strlike("%</body>%", zFooter, 0)==0 ){ |
| 892 | style_load_all_js_files(); |
| 893 | } |
| 894 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| @@ -1195,11 +1204,11 @@ | |
| 1195 | @ <pre> |
| 1196 | @ %h(blob_str(&g.httpHeader)) |
| 1197 | @ </pre> |
| 1198 | } |
| 1199 | } |
| 1200 | style_footer(); |
| 1201 | if( zErr ){ |
| 1202 | cgi_reply(); |
| 1203 | fossil_exit(1); |
| 1204 | } |
| 1205 | } |
| 1206 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -736,13 +736,28 @@ | |
| 736 | @ </script> |
| 737 | builtin_fulfill_js_requests(); |
| 738 | } |
| 739 | |
| 740 | /* |
| 741 | ** Invoke this routine after all of the content for a webpage has been |
| 742 | ** generated. This routine should be called once for every webpage, at |
| 743 | ** or near the end of page generation. This routine does the following: |
| 744 | ** |
| 745 | ** * Populates the header of the page, including setting up appropriate |
| 746 | ** submenu elements. The header generation is deferred until this point |
| 747 | ** so that we know that all style_submenu_element() and similar have |
| 748 | ** been received. |
| 749 | ** |
| 750 | ** * Finalizes the page content. |
| 751 | ** |
| 752 | ** * Appends the footer. |
| 753 | ** |
| 754 | ** The zPageType argument is a class name inserted in the <div> that |
| 755 | ** surrounds the page content. CSS can use this to have different styles |
| 756 | ** according to the page type. |
| 757 | */ |
| 758 | void style_finish_page(const char* zPageType){ |
| 759 | const char *zFooter; |
| 760 | const char *zAd = 0; |
| 761 | unsigned int mAdFlags = 0; |
| 762 | |
| 763 | if( !headerHasBeenGenerated ) return; |
| @@ -864,31 +879,25 @@ | |
| 879 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| 880 | @ <div class="content adunit_right_container"> |
| 881 | @ <div class="adunit_right"> |
| 882 | cgi_append_content(zAd, -1); |
| 883 | @ </div> |
| 884 | }else if( zAd ){ |
| 885 | @ <div class="adunit_banner"> |
| 886 | cgi_append_content(zAd, -1); |
| 887 | @ </div> |
| 888 | } |
| 889 | |
| 890 | @ <div class="content %s(zPageType)"><span id="debugMsg"></span> |
| 891 | cgi_destination(CGI_BODY); |
| 892 | |
| 893 | if( sideboxUsed ){ |
| 894 | @ <div class="endContent"></div> |
| 895 | } |
| 896 | @ </div> |
| 897 | |
| 898 | /* Put the footer at the bottom of the page. */ |
| 899 | zFooter = skin_get("footer"); |
| 900 | if( sqlite3_strlike("%</body>%", zFooter, 0)==0 ){ |
| 901 | style_load_all_js_files(); |
| 902 | } |
| 903 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| @@ -1195,11 +1204,11 @@ | |
| 1204 | @ <pre> |
| 1205 | @ %h(blob_str(&g.httpHeader)) |
| 1206 | @ </pre> |
| 1207 | } |
| 1208 | } |
| 1209 | style_finish_page("error"); |
| 1210 | if( zErr ){ |
| 1211 | cgi_reply(); |
| 1212 | fossil_exit(1); |
| 1213 | } |
| 1214 | } |
| 1215 |
+2
-2
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -724,11 +724,11 @@ | ||
| 724 | 724 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 725 | 725 | } |
| 726 | 726 | } |
| 727 | 727 | @ </ul> |
| 728 | 728 | db_finalize(&q); |
| 729 | - style_footer(); | |
| 729 | + style_finish_page("taglist"); | |
| 730 | 730 | } |
| 731 | 731 | |
| 732 | 732 | /* |
| 733 | 733 | ** WEBPAGE: /tagtimeline |
| 734 | 734 | ** |
| @@ -781,7 +781,7 @@ | ||
| 781 | 781 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; |
| 782 | 782 | if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; |
| 783 | 783 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); |
| 784 | 784 | db_finalize(&q); |
| 785 | 785 | @ <br /> |
| 786 | - style_footer(); | |
| 786 | + style_finish_page("tagtimeline"); | |
| 787 | 787 | } |
| 788 | 788 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -724,11 +724,11 @@ | |
| 724 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 725 | } |
| 726 | } |
| 727 | @ </ul> |
| 728 | db_finalize(&q); |
| 729 | style_footer(); |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | ** WEBPAGE: /tagtimeline |
| 734 | ** |
| @@ -781,7 +781,7 @@ | |
| 781 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; |
| 782 | if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; |
| 783 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); |
| 784 | db_finalize(&q); |
| 785 | @ <br /> |
| 786 | style_footer(); |
| 787 | } |
| 788 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -724,11 +724,11 @@ | |
| 724 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 725 | } |
| 726 | } |
| 727 | @ </ul> |
| 728 | db_finalize(&q); |
| 729 | style_finish_page("taglist"); |
| 730 | } |
| 731 | |
| 732 | /* |
| 733 | ** WEBPAGE: /tagtimeline |
| 734 | ** |
| @@ -781,7 +781,7 @@ | |
| 781 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; |
| 782 | if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; |
| 783 | www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); |
| 784 | db_finalize(&q); |
| 785 | @ <br /> |
| 786 | style_finish_page("tagtimeline"); |
| 787 | } |
| 788 |
+2
-2
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -785,11 +785,11 @@ | ||
| 785 | 785 | } |
| 786 | 786 | if( zExclude ){ |
| 787 | 787 | @ zExclude = "%h(zExclude)"<br /> |
| 788 | 788 | } |
| 789 | 789 | @ zKey = "%h(zKey)" |
| 790 | - style_footer(); | |
| 790 | + style_finish_page("tarball"); | |
| 791 | 791 | return; |
| 792 | 792 | } |
| 793 | 793 | if( referred_from_login() ){ |
| 794 | 794 | style_header("Tarball Download"); |
| 795 | 795 | @ <form action='%R/tarball/%h(zName).tar.gz'> |
| @@ -796,11 +796,11 @@ | ||
| 796 | 796 | cgi_query_parameters_to_hidden(); |
| 797 | 797 | @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content |
| 798 | 798 | @ of check-in <b>%h(zRid)</b>: |
| 799 | 799 | @ <input type="submit" value="Download" /> |
| 800 | 800 | @ </form> |
| 801 | - style_footer(); | |
| 801 | + style_finish_page("tarball"); | |
| 802 | 802 | return; |
| 803 | 803 | } |
| 804 | 804 | blob_zero(&tarball); |
| 805 | 805 | if( cache_read(&tarball, zKey)==0 ){ |
| 806 | 806 | tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); |
| 807 | 807 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -785,11 +785,11 @@ | |
| 785 | } |
| 786 | if( zExclude ){ |
| 787 | @ zExclude = "%h(zExclude)"<br /> |
| 788 | } |
| 789 | @ zKey = "%h(zKey)" |
| 790 | style_footer(); |
| 791 | return; |
| 792 | } |
| 793 | if( referred_from_login() ){ |
| 794 | style_header("Tarball Download"); |
| 795 | @ <form action='%R/tarball/%h(zName).tar.gz'> |
| @@ -796,11 +796,11 @@ | |
| 796 | cgi_query_parameters_to_hidden(); |
| 797 | @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content |
| 798 | @ of check-in <b>%h(zRid)</b>: |
| 799 | @ <input type="submit" value="Download" /> |
| 800 | @ </form> |
| 801 | style_footer(); |
| 802 | return; |
| 803 | } |
| 804 | blob_zero(&tarball); |
| 805 | if( cache_read(&tarball, zKey)==0 ){ |
| 806 | tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); |
| 807 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -785,11 +785,11 @@ | |
| 785 | } |
| 786 | if( zExclude ){ |
| 787 | @ zExclude = "%h(zExclude)"<br /> |
| 788 | } |
| 789 | @ zKey = "%h(zKey)" |
| 790 | style_finish_page("tarball"); |
| 791 | return; |
| 792 | } |
| 793 | if( referred_from_login() ){ |
| 794 | style_header("Tarball Download"); |
| 795 | @ <form action='%R/tarball/%h(zName).tar.gz'> |
| @@ -796,11 +796,11 @@ | |
| 796 | cgi_query_parameters_to_hidden(); |
| 797 | @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content |
| 798 | @ of check-in <b>%h(zRid)</b>: |
| 799 | @ <input type="submit" value="Download" /> |
| 800 | @ </form> |
| 801 | style_finish_page("tarball"); |
| 802 | return; |
| 803 | } |
| 804 | blob_zero(&tarball); |
| 805 | if( cache_read(&tarball, zKey)==0 ){ |
| 806 | tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude); |
| 807 |
+1
-1
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -1478,11 +1478,11 @@ | ||
| 1478 | 1478 | ){ |
| 1479 | 1479 | if( argc!=1 ){ |
| 1480 | 1480 | return Th_WrongNumArgs(interp, "styleFooter"); |
| 1481 | 1481 | } |
| 1482 | 1482 | if( Th_IsRepositoryOpen() ){ |
| 1483 | - style_footer(); | |
| 1483 | + style_finish_page("th1"); /* TODO: add optional parameter to pass along? */ | |
| 1484 | 1484 | Th_SetResult(interp, 0, 0); |
| 1485 | 1485 | return TH_OK; |
| 1486 | 1486 | }else{ |
| 1487 | 1487 | Th_SetResult(interp, "repository unavailable", -1); |
| 1488 | 1488 | return TH_ERROR; |
| 1489 | 1489 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1478,11 +1478,11 @@ | |
| 1478 | ){ |
| 1479 | if( argc!=1 ){ |
| 1480 | return Th_WrongNumArgs(interp, "styleFooter"); |
| 1481 | } |
| 1482 | if( Th_IsRepositoryOpen() ){ |
| 1483 | style_footer(); |
| 1484 | Th_SetResult(interp, 0, 0); |
| 1485 | return TH_OK; |
| 1486 | }else{ |
| 1487 | Th_SetResult(interp, "repository unavailable", -1); |
| 1488 | return TH_ERROR; |
| 1489 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1478,11 +1478,11 @@ | |
| 1478 | ){ |
| 1479 | if( argc!=1 ){ |
| 1480 | return Th_WrongNumArgs(interp, "styleFooter"); |
| 1481 | } |
| 1482 | if( Th_IsRepositoryOpen() ){ |
| 1483 | style_finish_page("th1"); /* TODO: add optional parameter to pass along? */ |
| 1484 | Th_SetResult(interp, 0, 0); |
| 1485 | return TH_OK; |
| 1486 | }else{ |
| 1487 | Th_SetResult(interp, "repository unavailable", -1); |
| 1488 | return TH_ERROR; |
| 1489 |
+4
-4
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -214,11 +214,11 @@ | ||
| 214 | 214 | zBr = P(zNm); |
| 215 | 215 | @ <input type="text" size="30" name='%s(zNm)' value='%h(PD(zNm,""))'><br /> |
| 216 | 216 | } |
| 217 | 217 | @ <input type="submit"> |
| 218 | 218 | @ </form> |
| 219 | - style_footer(); | |
| 219 | + style_finish_page("test"); | |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | /* |
| 223 | 223 | ** Return a new timelineTable id. |
| 224 | 224 | */ |
| @@ -2625,11 +2625,11 @@ | ||
| 2625 | 2625 | db_finalize(&q); |
| 2626 | 2626 | if( zOlderButton ){ |
| 2627 | 2627 | @ %z(chref("button","%z",zOlderButton))More ↓</a> |
| 2628 | 2628 | } |
| 2629 | 2629 | document_emit_js(/*handles pikchrs rendered above*/); |
| 2630 | - style_footer(); | |
| 2630 | + style_finish_page("timeline"); | |
| 2631 | 2631 | } |
| 2632 | 2632 | |
| 2633 | 2633 | /* |
| 2634 | 2634 | ** The input query q selects various records. Print a human-readable |
| 2635 | 2635 | ** summary of those records. |
| @@ -3117,11 +3117,11 @@ | ||
| 3117 | 3117 | @ <small>%z(href("%R/timeline?c=%t",zId))(more context)</a>\ |
| 3118 | 3118 | @ </small></h2> |
| 3119 | 3119 | www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0); |
| 3120 | 3120 | } |
| 3121 | 3121 | db_finalize(&q); |
| 3122 | - style_footer(); | |
| 3122 | + style_finish_page("timeline"); | |
| 3123 | 3123 | } |
| 3124 | 3124 | |
| 3125 | 3125 | |
| 3126 | 3126 | /* |
| 3127 | 3127 | ** COMMAND: test-timewarp-list |
| @@ -3223,7 +3223,7 @@ | ||
| 3223 | 3223 | if( cnt==0 ){ |
| 3224 | 3224 | @ <p>No timewarps in this repository</p> |
| 3225 | 3225 | }else{ |
| 3226 | 3226 | @ </tbody></table></div> |
| 3227 | 3227 | } |
| 3228 | - style_footer(); | |
| 3228 | + style_finish_page("timewarps"); | |
| 3229 | 3229 | } |
| 3230 | 3230 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -214,11 +214,11 @@ | |
| 214 | zBr = P(zNm); |
| 215 | @ <input type="text" size="30" name='%s(zNm)' value='%h(PD(zNm,""))'><br /> |
| 216 | } |
| 217 | @ <input type="submit"> |
| 218 | @ </form> |
| 219 | style_footer(); |
| 220 | } |
| 221 | |
| 222 | /* |
| 223 | ** Return a new timelineTable id. |
| 224 | */ |
| @@ -2625,11 +2625,11 @@ | |
| 2625 | db_finalize(&q); |
| 2626 | if( zOlderButton ){ |
| 2627 | @ %z(chref("button","%z",zOlderButton))More ↓</a> |
| 2628 | } |
| 2629 | document_emit_js(/*handles pikchrs rendered above*/); |
| 2630 | style_footer(); |
| 2631 | } |
| 2632 | |
| 2633 | /* |
| 2634 | ** The input query q selects various records. Print a human-readable |
| 2635 | ** summary of those records. |
| @@ -3117,11 +3117,11 @@ | |
| 3117 | @ <small>%z(href("%R/timeline?c=%t",zId))(more context)</a>\ |
| 3118 | @ </small></h2> |
| 3119 | www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0); |
| 3120 | } |
| 3121 | db_finalize(&q); |
| 3122 | style_footer(); |
| 3123 | } |
| 3124 | |
| 3125 | |
| 3126 | /* |
| 3127 | ** COMMAND: test-timewarp-list |
| @@ -3223,7 +3223,7 @@ | |
| 3223 | if( cnt==0 ){ |
| 3224 | @ <p>No timewarps in this repository</p> |
| 3225 | }else{ |
| 3226 | @ </tbody></table></div> |
| 3227 | } |
| 3228 | style_footer(); |
| 3229 | } |
| 3230 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -214,11 +214,11 @@ | |
| 214 | zBr = P(zNm); |
| 215 | @ <input type="text" size="30" name='%s(zNm)' value='%h(PD(zNm,""))'><br /> |
| 216 | } |
| 217 | @ <input type="submit"> |
| 218 | @ </form> |
| 219 | style_finish_page("test"); |
| 220 | } |
| 221 | |
| 222 | /* |
| 223 | ** Return a new timelineTable id. |
| 224 | */ |
| @@ -2625,11 +2625,11 @@ | |
| 2625 | db_finalize(&q); |
| 2626 | if( zOlderButton ){ |
| 2627 | @ %z(chref("button","%z",zOlderButton))More ↓</a> |
| 2628 | } |
| 2629 | document_emit_js(/*handles pikchrs rendered above*/); |
| 2630 | style_finish_page("timeline"); |
| 2631 | } |
| 2632 | |
| 2633 | /* |
| 2634 | ** The input query q selects various records. Print a human-readable |
| 2635 | ** summary of those records. |
| @@ -3117,11 +3117,11 @@ | |
| 3117 | @ <small>%z(href("%R/timeline?c=%t",zId))(more context)</a>\ |
| 3118 | @ </small></h2> |
| 3119 | www_print_timeline(&q, TIMELINE_GRAPH, 0, 0, 0, 0, 0, 0); |
| 3120 | } |
| 3121 | db_finalize(&q); |
| 3122 | style_finish_page("timeline"); |
| 3123 | } |
| 3124 | |
| 3125 | |
| 3126 | /* |
| 3127 | ** COMMAND: test-timewarp-list |
| @@ -3223,7 +3223,7 @@ | |
| 3223 | if( cnt==0 ){ |
| 3224 | @ <p>No timewarps in this repository</p> |
| 3225 | }else{ |
| 3226 | @ </tbody></table></div> |
| 3227 | } |
| 3228 | style_finish_page("timewarps"); |
| 3229 | } |
| 3230 |
+11
-11
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -617,11 +617,11 @@ | ||
| 617 | 617 | " WHERE tkt_uuid GLOB '%q*'", zUuid); |
| 618 | 618 | if( zFullName ){ |
| 619 | 619 | attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>"); |
| 620 | 620 | } |
| 621 | 621 | |
| 622 | - style_footer(); | |
| 622 | + style_finish_page("tkt"); | |
| 623 | 623 | } |
| 624 | 624 | |
| 625 | 625 | /* |
| 626 | 626 | ** TH1 command: append_field FIELD STRING |
| 627 | 627 | ** |
| @@ -840,11 +840,11 @@ | ||
| 840 | 840 | return; |
| 841 | 841 | } |
| 842 | 842 | captcha_generate(0); |
| 843 | 843 | @ </form> |
| 844 | 844 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 845 | - style_footer(); | |
| 845 | + style_finish_page("tkt"); | |
| 846 | 846 | } |
| 847 | 847 | |
| 848 | 848 | /* |
| 849 | 849 | ** WEBPAGE: tktedit |
| 850 | 850 | ** WEBPAGE: debug_tktedit |
| @@ -873,24 +873,24 @@ | ||
| 873 | 873 | } |
| 874 | 874 | style_header("Edit Ticket"); |
| 875 | 875 | if( zName==0 || (nName = strlen(zName))<4 || nName>HNAME_LEN_SHA1 |
| 876 | 876 | || !validate16(zName,nName) ){ |
| 877 | 877 | @ <span class="tktError">Not a valid ticket id: "%h(zName)"</span> |
| 878 | - style_footer(); | |
| 878 | + style_finish_page("tkt"); | |
| 879 | 879 | return; |
| 880 | 880 | } |
| 881 | 881 | nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'", |
| 882 | 882 | zName); |
| 883 | 883 | if( nRec==0 ){ |
| 884 | 884 | @ <span class="tktError">No such ticket: "%h(zName)"</span> |
| 885 | - style_footer(); | |
| 885 | + style_finish_page("tkt"); | |
| 886 | 886 | return; |
| 887 | 887 | } |
| 888 | 888 | if( nRec>1 ){ |
| 889 | 889 | @ <span class="tktError">%d(nRec) tickets begin with: |
| 890 | 890 | @ "%h(zName)"</span> |
| 891 | - style_footer(); | |
| 891 | + style_finish_page("tkt"); | |
| 892 | 892 | return; |
| 893 | 893 | } |
| 894 | 894 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 895 | 895 | ticket_init(); |
| 896 | 896 | getAllTicketFields(); |
| @@ -911,11 +911,11 @@ | ||
| 911 | 911 | return; |
| 912 | 912 | } |
| 913 | 913 | captcha_generate(0); |
| 914 | 914 | @ </form> |
| 915 | 915 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 916 | - style_footer(); | |
| 916 | + style_finish_page("tkt"); | |
| 917 | 917 | } |
| 918 | 918 | |
| 919 | 919 | /* |
| 920 | 920 | ** Check the ticket table schema in zSchema to see if it appears to |
| 921 | 921 | ** be well-formed. If everything is OK, return NULL. If something is |
| @@ -1041,15 +1041,15 @@ | ||
| 1041 | 1041 | sqlite3_snprintf(6, zGlobPattern, "%s", zUuid); |
| 1042 | 1042 | canonical16(zGlobPattern, strlen(zGlobPattern)); |
| 1043 | 1043 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 1044 | 1044 | if( tagid==0 ){ |
| 1045 | 1045 | @ No such ticket: %h(zUuid) |
| 1046 | - style_footer(); | |
| 1046 | + style_finish_page("tkt"); | |
| 1047 | 1047 | return; |
| 1048 | 1048 | } |
| 1049 | 1049 | tkt_draw_timeline(tagid, zType); |
| 1050 | - style_footer(); | |
| 1050 | + style_finish_page("tkt"); | |
| 1051 | 1051 | } |
| 1052 | 1052 | |
| 1053 | 1053 | /* |
| 1054 | 1054 | ** WEBPAGE: tkthistory |
| 1055 | 1055 | ** URL: /tkthistory?name=TICKETUUID |
| @@ -1088,11 +1088,11 @@ | ||
| 1088 | 1088 | style_header("%z", zTitle); |
| 1089 | 1089 | |
| 1090 | 1090 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 1091 | 1091 | if( tagid==0 ){ |
| 1092 | 1092 | @ No such ticket: %h(zUuid) |
| 1093 | - style_footer(); | |
| 1093 | + style_finish_page("tkt"); | |
| 1094 | 1094 | return; |
| 1095 | 1095 | } |
| 1096 | 1096 | if( P("raw")!=0 ){ |
| 1097 | 1097 | @ <h2>Raw Artifacts Associated With Ticket %h(zUuid)</h2> |
| 1098 | 1098 | }else{ |
| @@ -1161,11 +1161,11 @@ | ||
| 1161 | 1161 | } |
| 1162 | 1162 | db_finalize(&q); |
| 1163 | 1163 | if( nChng ){ |
| 1164 | 1164 | @ </ol> |
| 1165 | 1165 | } |
| 1166 | - style_footer(); | |
| 1166 | + style_finish_page("tkt"); | |
| 1167 | 1167 | } |
| 1168 | 1168 | |
| 1169 | 1169 | /* |
| 1170 | 1170 | ** Return TRUE if the given BLOB contains a newline character. |
| 1171 | 1171 | */ |
| @@ -1613,7 +1613,7 @@ | ||
| 1613 | 1613 | void tkt_srchpage(void){ |
| 1614 | 1614 | login_check_credentials(); |
| 1615 | 1615 | style_header("Ticket Search"); |
| 1616 | 1616 | ticket_standard_submenu(T_ALL_BUT(T_SRCH)); |
| 1617 | 1617 | search_screen(SRCH_TKT, 0); |
| 1618 | - style_footer(); | |
| 1618 | + style_finish_page("tkt"); | |
| 1619 | 1619 | } |
| 1620 | 1620 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -617,11 +617,11 @@ | |
| 617 | " WHERE tkt_uuid GLOB '%q*'", zUuid); |
| 618 | if( zFullName ){ |
| 619 | attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>"); |
| 620 | } |
| 621 | |
| 622 | style_footer(); |
| 623 | } |
| 624 | |
| 625 | /* |
| 626 | ** TH1 command: append_field FIELD STRING |
| 627 | ** |
| @@ -840,11 +840,11 @@ | |
| 840 | return; |
| 841 | } |
| 842 | captcha_generate(0); |
| 843 | @ </form> |
| 844 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 845 | style_footer(); |
| 846 | } |
| 847 | |
| 848 | /* |
| 849 | ** WEBPAGE: tktedit |
| 850 | ** WEBPAGE: debug_tktedit |
| @@ -873,24 +873,24 @@ | |
| 873 | } |
| 874 | style_header("Edit Ticket"); |
| 875 | if( zName==0 || (nName = strlen(zName))<4 || nName>HNAME_LEN_SHA1 |
| 876 | || !validate16(zName,nName) ){ |
| 877 | @ <span class="tktError">Not a valid ticket id: "%h(zName)"</span> |
| 878 | style_footer(); |
| 879 | return; |
| 880 | } |
| 881 | nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'", |
| 882 | zName); |
| 883 | if( nRec==0 ){ |
| 884 | @ <span class="tktError">No such ticket: "%h(zName)"</span> |
| 885 | style_footer(); |
| 886 | return; |
| 887 | } |
| 888 | if( nRec>1 ){ |
| 889 | @ <span class="tktError">%d(nRec) tickets begin with: |
| 890 | @ "%h(zName)"</span> |
| 891 | style_footer(); |
| 892 | return; |
| 893 | } |
| 894 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 895 | ticket_init(); |
| 896 | getAllTicketFields(); |
| @@ -911,11 +911,11 @@ | |
| 911 | return; |
| 912 | } |
| 913 | captcha_generate(0); |
| 914 | @ </form> |
| 915 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 916 | style_footer(); |
| 917 | } |
| 918 | |
| 919 | /* |
| 920 | ** Check the ticket table schema in zSchema to see if it appears to |
| 921 | ** be well-formed. If everything is OK, return NULL. If something is |
| @@ -1041,15 +1041,15 @@ | |
| 1041 | sqlite3_snprintf(6, zGlobPattern, "%s", zUuid); |
| 1042 | canonical16(zGlobPattern, strlen(zGlobPattern)); |
| 1043 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 1044 | if( tagid==0 ){ |
| 1045 | @ No such ticket: %h(zUuid) |
| 1046 | style_footer(); |
| 1047 | return; |
| 1048 | } |
| 1049 | tkt_draw_timeline(tagid, zType); |
| 1050 | style_footer(); |
| 1051 | } |
| 1052 | |
| 1053 | /* |
| 1054 | ** WEBPAGE: tkthistory |
| 1055 | ** URL: /tkthistory?name=TICKETUUID |
| @@ -1088,11 +1088,11 @@ | |
| 1088 | style_header("%z", zTitle); |
| 1089 | |
| 1090 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 1091 | if( tagid==0 ){ |
| 1092 | @ No such ticket: %h(zUuid) |
| 1093 | style_footer(); |
| 1094 | return; |
| 1095 | } |
| 1096 | if( P("raw")!=0 ){ |
| 1097 | @ <h2>Raw Artifacts Associated With Ticket %h(zUuid)</h2> |
| 1098 | }else{ |
| @@ -1161,11 +1161,11 @@ | |
| 1161 | } |
| 1162 | db_finalize(&q); |
| 1163 | if( nChng ){ |
| 1164 | @ </ol> |
| 1165 | } |
| 1166 | style_footer(); |
| 1167 | } |
| 1168 | |
| 1169 | /* |
| 1170 | ** Return TRUE if the given BLOB contains a newline character. |
| 1171 | */ |
| @@ -1613,7 +1613,7 @@ | |
| 1613 | void tkt_srchpage(void){ |
| 1614 | login_check_credentials(); |
| 1615 | style_header("Ticket Search"); |
| 1616 | ticket_standard_submenu(T_ALL_BUT(T_SRCH)); |
| 1617 | search_screen(SRCH_TKT, 0); |
| 1618 | style_footer(); |
| 1619 | } |
| 1620 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -617,11 +617,11 @@ | |
| 617 | " WHERE tkt_uuid GLOB '%q*'", zUuid); |
| 618 | if( zFullName ){ |
| 619 | attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>"); |
| 620 | } |
| 621 | |
| 622 | style_finish_page("tkt"); |
| 623 | } |
| 624 | |
| 625 | /* |
| 626 | ** TH1 command: append_field FIELD STRING |
| 627 | ** |
| @@ -840,11 +840,11 @@ | |
| 840 | return; |
| 841 | } |
| 842 | captcha_generate(0); |
| 843 | @ </form> |
| 844 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 845 | style_finish_page("tkt"); |
| 846 | } |
| 847 | |
| 848 | /* |
| 849 | ** WEBPAGE: tktedit |
| 850 | ** WEBPAGE: debug_tktedit |
| @@ -873,24 +873,24 @@ | |
| 873 | } |
| 874 | style_header("Edit Ticket"); |
| 875 | if( zName==0 || (nName = strlen(zName))<4 || nName>HNAME_LEN_SHA1 |
| 876 | || !validate16(zName,nName) ){ |
| 877 | @ <span class="tktError">Not a valid ticket id: "%h(zName)"</span> |
| 878 | style_finish_page("tkt"); |
| 879 | return; |
| 880 | } |
| 881 | nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'", |
| 882 | zName); |
| 883 | if( nRec==0 ){ |
| 884 | @ <span class="tktError">No such ticket: "%h(zName)"</span> |
| 885 | style_finish_page("tkt"); |
| 886 | return; |
| 887 | } |
| 888 | if( nRec>1 ){ |
| 889 | @ <span class="tktError">%d(nRec) tickets begin with: |
| 890 | @ "%h(zName)"</span> |
| 891 | style_finish_page("tkt"); |
| 892 | return; |
| 893 | } |
| 894 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 895 | ticket_init(); |
| 896 | getAllTicketFields(); |
| @@ -911,11 +911,11 @@ | |
| 911 | return; |
| 912 | } |
| 913 | captcha_generate(0); |
| 914 | @ </form> |
| 915 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 916 | style_finish_page("tkt"); |
| 917 | } |
| 918 | |
| 919 | /* |
| 920 | ** Check the ticket table schema in zSchema to see if it appears to |
| 921 | ** be well-formed. If everything is OK, return NULL. If something is |
| @@ -1041,15 +1041,15 @@ | |
| 1041 | sqlite3_snprintf(6, zGlobPattern, "%s", zUuid); |
| 1042 | canonical16(zGlobPattern, strlen(zGlobPattern)); |
| 1043 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 1044 | if( tagid==0 ){ |
| 1045 | @ No such ticket: %h(zUuid) |
| 1046 | style_finish_page("tkt"); |
| 1047 | return; |
| 1048 | } |
| 1049 | tkt_draw_timeline(tagid, zType); |
| 1050 | style_finish_page("tkt"); |
| 1051 | } |
| 1052 | |
| 1053 | /* |
| 1054 | ** WEBPAGE: tkthistory |
| 1055 | ** URL: /tkthistory?name=TICKETUUID |
| @@ -1088,11 +1088,11 @@ | |
| 1088 | style_header("%z", zTitle); |
| 1089 | |
| 1090 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid); |
| 1091 | if( tagid==0 ){ |
| 1092 | @ No such ticket: %h(zUuid) |
| 1093 | style_finish_page("tkt"); |
| 1094 | return; |
| 1095 | } |
| 1096 | if( P("raw")!=0 ){ |
| 1097 | @ <h2>Raw Artifacts Associated With Ticket %h(zUuid)</h2> |
| 1098 | }else{ |
| @@ -1161,11 +1161,11 @@ | |
| 1161 | } |
| 1162 | db_finalize(&q); |
| 1163 | if( nChng ){ |
| 1164 | @ </ol> |
| 1165 | } |
| 1166 | style_finish_page("tkt"); |
| 1167 | } |
| 1168 | |
| 1169 | /* |
| 1170 | ** Return TRUE if the given BLOB contains a newline character. |
| 1171 | */ |
| @@ -1613,7 +1613,7 @@ | |
| 1613 | void tkt_srchpage(void){ |
| 1614 | login_check_credentials(); |
| 1615 | style_header("Ticket Search"); |
| 1616 | ticket_standard_submenu(T_ALL_BUT(T_SRCH)); |
| 1617 | search_screen(SRCH_TKT, 0); |
| 1618 | style_finish_page("tkt"); |
| 1619 | } |
| 1620 |
+3
-3
| --- src/tktsetup.c | ||
| +++ src/tktsetup.c | ||
| @@ -54,11 +54,11 @@ | ||
| 54 | 54 | setup_menu_entry("Report Template", "tktsetup_rpttplt", |
| 55 | 55 | "The default ticket report format."); |
| 56 | 56 | setup_menu_entry("Key Template", "tktsetup_keytplt", |
| 57 | 57 | "The default color key for reports."); |
| 58 | 58 | @ </table> |
| 59 | - style_footer(); | |
| 59 | + style_finish_page("tktsetup"); | |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | /* |
| 63 | 63 | ** NOTE: When changing the table definition below, also change the |
| 64 | 64 | ** equivalent definition found in schema.c. |
| @@ -163,11 +163,11 @@ | ||
| 163 | 163 | @ <hr /> |
| 164 | 164 | @ <h2>Default %s(zTitle)</h2> |
| 165 | 165 | @ <blockquote><pre> |
| 166 | 166 | @ %h(zDfltValue) |
| 167 | 167 | @ </pre></blockquote> |
| 168 | - style_footer(); | |
| 168 | + style_finish_page("tktsetup"); | |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | 171 | /* |
| 172 | 172 | ** WEBPAGE: tktsetup_tab |
| 173 | 173 | ** Administrative page for defining the "ticket" table used |
| @@ -934,8 +934,8 @@ | ||
| 934 | 934 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 935 | 935 | @ <input type="submit" name="setup" value="Cancel" /> |
| 936 | 936 | @ </p> |
| 937 | 937 | @ </div></form> |
| 938 | 938 | db_end_transaction(0); |
| 939 | - style_footer(); | |
| 939 | + style_finish_page("tktsetup"); | |
| 940 | 940 | |
| 941 | 941 | } |
| 942 | 942 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -54,11 +54,11 @@ | |
| 54 | setup_menu_entry("Report Template", "tktsetup_rpttplt", |
| 55 | "The default ticket report format."); |
| 56 | setup_menu_entry("Key Template", "tktsetup_keytplt", |
| 57 | "The default color key for reports."); |
| 58 | @ </table> |
| 59 | style_footer(); |
| 60 | } |
| 61 | |
| 62 | /* |
| 63 | ** NOTE: When changing the table definition below, also change the |
| 64 | ** equivalent definition found in schema.c. |
| @@ -163,11 +163,11 @@ | |
| 163 | @ <hr /> |
| 164 | @ <h2>Default %s(zTitle)</h2> |
| 165 | @ <blockquote><pre> |
| 166 | @ %h(zDfltValue) |
| 167 | @ </pre></blockquote> |
| 168 | style_footer(); |
| 169 | } |
| 170 | |
| 171 | /* |
| 172 | ** WEBPAGE: tktsetup_tab |
| 173 | ** Administrative page for defining the "ticket" table used |
| @@ -934,8 +934,8 @@ | |
| 934 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 935 | @ <input type="submit" name="setup" value="Cancel" /> |
| 936 | @ </p> |
| 937 | @ </div></form> |
| 938 | db_end_transaction(0); |
| 939 | style_footer(); |
| 940 | |
| 941 | } |
| 942 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -54,11 +54,11 @@ | |
| 54 | setup_menu_entry("Report Template", "tktsetup_rpttplt", |
| 55 | "The default ticket report format."); |
| 56 | setup_menu_entry("Key Template", "tktsetup_keytplt", |
| 57 | "The default color key for reports."); |
| 58 | @ </table> |
| 59 | style_finish_page("tktsetup"); |
| 60 | } |
| 61 | |
| 62 | /* |
| 63 | ** NOTE: When changing the table definition below, also change the |
| 64 | ** equivalent definition found in schema.c. |
| @@ -163,11 +163,11 @@ | |
| 163 | @ <hr /> |
| 164 | @ <h2>Default %s(zTitle)</h2> |
| 165 | @ <blockquote><pre> |
| 166 | @ %h(zDfltValue) |
| 167 | @ </pre></blockquote> |
| 168 | style_finish_page("tktsetup"); |
| 169 | } |
| 170 | |
| 171 | /* |
| 172 | ** WEBPAGE: tktsetup_tab |
| 173 | ** Administrative page for defining the "ticket" table used |
| @@ -934,8 +934,8 @@ | |
| 934 | @ <input type="submit" name="submit" value="Apply Changes" /> |
| 935 | @ <input type="submit" name="setup" value="Cancel" /> |
| 936 | @ </p> |
| 937 | @ </div></form> |
| 938 | db_end_transaction(0); |
| 939 | style_finish_page("tktsetup"); |
| 940 | |
| 941 | } |
| 942 |
+2
-2
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -546,11 +546,11 @@ | ||
| 546 | 546 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 547 | 547 | etag_check(ETAG_DATA,0); |
| 548 | 548 | style_header("Unversioned Files"); |
| 549 | 549 | if( !db_table_exists("repository","unversioned") ){ |
| 550 | 550 | @ No unversioned files on this server |
| 551 | - style_footer(); | |
| 551 | + style_finish_page("uvlist"); | |
| 552 | 552 | return; |
| 553 | 553 | } |
| 554 | 554 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 555 | 555 | if( PB("showdel") ) showDel = 1; |
| 556 | 556 | db_prepare(&q, |
| @@ -632,11 +632,11 @@ | ||
| 632 | 632 | @ </tfoot> |
| 633 | 633 | @ </table></div> |
| 634 | 634 | }else{ |
| 635 | 635 | @ No unversioned files on this server. |
| 636 | 636 | } |
| 637 | - style_footer(); | |
| 637 | + style_finish_page("uvlist"); | |
| 638 | 638 | } |
| 639 | 639 | |
| 640 | 640 | /* |
| 641 | 641 | ** WEBPAGE: juvlist |
| 642 | 642 | ** |
| 643 | 643 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -546,11 +546,11 @@ | |
| 546 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 547 | etag_check(ETAG_DATA,0); |
| 548 | style_header("Unversioned Files"); |
| 549 | if( !db_table_exists("repository","unversioned") ){ |
| 550 | @ No unversioned files on this server |
| 551 | style_footer(); |
| 552 | return; |
| 553 | } |
| 554 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 555 | if( PB("showdel") ) showDel = 1; |
| 556 | db_prepare(&q, |
| @@ -632,11 +632,11 @@ | |
| 632 | @ </tfoot> |
| 633 | @ </table></div> |
| 634 | }else{ |
| 635 | @ No unversioned files on this server. |
| 636 | } |
| 637 | style_footer(); |
| 638 | } |
| 639 | |
| 640 | /* |
| 641 | ** WEBPAGE: juvlist |
| 642 | ** |
| 643 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -546,11 +546,11 @@ | |
| 546 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 547 | etag_check(ETAG_DATA,0); |
| 548 | style_header("Unversioned Files"); |
| 549 | if( !db_table_exists("repository","unversioned") ){ |
| 550 | @ No unversioned files on this server |
| 551 | style_finish_page("uvlist"); |
| 552 | return; |
| 553 | } |
| 554 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 555 | if( PB("showdel") ) showDel = 1; |
| 556 | db_prepare(&q, |
| @@ -632,11 +632,11 @@ | |
| 632 | @ </tfoot> |
| 633 | @ </table></div> |
| 634 | }else{ |
| 635 | @ No unversioned files on this server. |
| 636 | } |
| 637 | style_finish_page("uvlist"); |
| 638 | } |
| 639 | |
| 640 | /* |
| 641 | ** WEBPAGE: juvlist |
| 642 | ** |
| 643 |
+49
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -628,5 +628,54 @@ | ||
| 628 | 628 | && isatty(fileno(stdin)) |
| 629 | 629 | ){ |
| 630 | 630 | url_prompt_for_password(); |
| 631 | 631 | } |
| 632 | 632 | } |
| 633 | + | |
| 634 | +/* | |
| 635 | +** Given a URL for a remote repository clone point, try to come up with a | |
| 636 | +** reasonable basename of a local clone of that repository. | |
| 637 | +** | |
| 638 | +** * If the URL has a path, use the tail of the path, with any suffix | |
| 639 | +** elided. | |
| 640 | +** | |
| 641 | +** * If the URL is just a domain name, without a path, then use the | |
| 642 | +** first element of the domain name, except skip over "www." if | |
| 643 | +** present. | |
| 644 | +** | |
| 645 | +** The string returned is obtained from fossil_malloc(). NULL might be | |
| 646 | +** returned if there is an error. | |
| 647 | +*/ | |
| 648 | +char *url_to_repo_basename(const char *zUrl){ | |
| 649 | + const char *zTail = 0; | |
| 650 | + int i; | |
| 651 | + if( zUrl==0 ) return 0; | |
| 652 | + for(i=0; zUrl[i]; i++){ | |
| 653 | + if( zUrl[i]=='?' ) break; | |
| 654 | + if( (zUrl[i]=='/' || zUrl[i]=='@') && zUrl[i+1]!=0 ) zTail = &zUrl[i+1]; | |
| 655 | + } | |
| 656 | + if( zTail==0 ) return 0; | |
| 657 | + if( sqlite3_strnicmp(zTail, "www.", 4)==0 ) zTail += 4; | |
| 658 | + if( zTail[0]==0 ) return 0; | |
| 659 | + for(i=0; zTail[i] && zTail[i]!='.' && zTail[i]!='?'; i++){} | |
| 660 | + if( i==0 ) return 0; | |
| 661 | + return mprintf("%.*s", i, zTail); | |
| 662 | +} | |
| 663 | + | |
| 664 | +/* | |
| 665 | +** COMMAND: test-url-basename | |
| 666 | +** Usage: %fossil test-url-basenames URL ... | |
| 667 | +** | |
| 668 | +** This command is used for unit testing of the url_to_repo_basename() | |
| 669 | +** routine. The command-line arguments are URL, presumably for remote | |
| 670 | +** Fossil repositories. This command runs url_to_repo_basename() on each | |
| 671 | +** of those inputs and displays the result. | |
| 672 | +*/ | |
| 673 | +void cmd_test_url_basename(void){ | |
| 674 | + int i; | |
| 675 | + char *z; | |
| 676 | + for(i=2; i<g.argc; i++){ | |
| 677 | + z = url_to_repo_basename(g.argv[i]); | |
| 678 | + fossil_print("%s -> %s\n", g.argv[i], z); | |
| 679 | + fossil_free(z); | |
| 680 | + } | |
| 681 | +} | |
| 633 | 682 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -628,5 +628,54 @@ | |
| 628 | && isatty(fileno(stdin)) |
| 629 | ){ |
| 630 | url_prompt_for_password(); |
| 631 | } |
| 632 | } |
| 633 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -628,5 +628,54 @@ | |
| 628 | && isatty(fileno(stdin)) |
| 629 | ){ |
| 630 | url_prompt_for_password(); |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | /* |
| 635 | ** Given a URL for a remote repository clone point, try to come up with a |
| 636 | ** reasonable basename of a local clone of that repository. |
| 637 | ** |
| 638 | ** * If the URL has a path, use the tail of the path, with any suffix |
| 639 | ** elided. |
| 640 | ** |
| 641 | ** * If the URL is just a domain name, without a path, then use the |
| 642 | ** first element of the domain name, except skip over "www." if |
| 643 | ** present. |
| 644 | ** |
| 645 | ** The string returned is obtained from fossil_malloc(). NULL might be |
| 646 | ** returned if there is an error. |
| 647 | */ |
| 648 | char *url_to_repo_basename(const char *zUrl){ |
| 649 | const char *zTail = 0; |
| 650 | int i; |
| 651 | if( zUrl==0 ) return 0; |
| 652 | for(i=0; zUrl[i]; i++){ |
| 653 | if( zUrl[i]=='?' ) break; |
| 654 | if( (zUrl[i]=='/' || zUrl[i]=='@') && zUrl[i+1]!=0 ) zTail = &zUrl[i+1]; |
| 655 | } |
| 656 | if( zTail==0 ) return 0; |
| 657 | if( sqlite3_strnicmp(zTail, "www.", 4)==0 ) zTail += 4; |
| 658 | if( zTail[0]==0 ) return 0; |
| 659 | for(i=0; zTail[i] && zTail[i]!='.' && zTail[i]!='?'; i++){} |
| 660 | if( i==0 ) return 0; |
| 661 | return mprintf("%.*s", i, zTail); |
| 662 | } |
| 663 | |
| 664 | /* |
| 665 | ** COMMAND: test-url-basename |
| 666 | ** Usage: %fossil test-url-basenames URL ... |
| 667 | ** |
| 668 | ** This command is used for unit testing of the url_to_repo_basename() |
| 669 | ** routine. The command-line arguments are URL, presumably for remote |
| 670 | ** Fossil repositories. This command runs url_to_repo_basename() on each |
| 671 | ** of those inputs and displays the result. |
| 672 | */ |
| 673 | void cmd_test_url_basename(void){ |
| 674 | int i; |
| 675 | char *z; |
| 676 | for(i=2; i<g.argc; i++){ |
| 677 | z = url_to_repo_basename(g.argv[i]); |
| 678 | fossil_print("%s -> %s\n", g.argv[i], z); |
| 679 | fossil_free(z); |
| 680 | } |
| 681 | } |
| 682 |
+24
-2
| --- src/user.c | ||
| +++ src/user.c | ||
| @@ -335,10 +335,14 @@ | ||
| 335 | 335 | ** |
| 336 | 336 | ** > fossil user capabilities USERNAME ?STRING? |
| 337 | 337 | ** |
| 338 | 338 | ** Query or set the capabilities for user USERNAME |
| 339 | 339 | ** |
| 340 | +** > fossil user contact USERNAME ?CONTACT-INFO? | |
| 341 | +** | |
| 342 | +** Query or set contact information for user USERNAME | |
| 343 | +** | |
| 340 | 344 | ** > fossil user default ?USERNAME? |
| 341 | 345 | ** |
| 342 | 346 | ** Query or set the default user. The default user is the |
| 343 | 347 | ** user for command-line interaction. |
| 344 | 348 | ** |
| @@ -458,13 +462,31 @@ | ||
| 458 | 462 | g.argv[4], uid |
| 459 | 463 | ); |
| 460 | 464 | db_protect_pop(); |
| 461 | 465 | } |
| 462 | 466 | fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid)); |
| 467 | + }else if( n>=2 && strncmp(g.argv[2], "contact", 2)==0 ){ | |
| 468 | + int uid; | |
| 469 | + if( g.argc!=4 && g.argc!=5 ){ | |
| 470 | + usage("contact USERNAME ?CONTACT-INFO?"); | |
| 471 | + } | |
| 472 | + uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]); | |
| 473 | + if( uid==0 ){ | |
| 474 | + fossil_fatal("no such user: %s", g.argv[3]); | |
| 475 | + } | |
| 476 | + if( g.argc==5 ){ | |
| 477 | + db_unprotect(PROTECT_USER); | |
| 478 | + db_multi_exec( | |
| 479 | + "UPDATE user SET info=%Q, mtime=now() WHERE uid=%d", | |
| 480 | + g.argv[4], uid | |
| 481 | + ); | |
| 482 | + db_protect_pop(); | |
| 483 | + } | |
| 484 | + fossil_print("%s\n", db_text(0, "SELECT info FROM user WHERE uid=%d", uid)); | |
| 463 | 485 | }else{ |
| 464 | 486 | fossil_fatal("user subcommand should be one of: " |
| 465 | - "capabilities default list new password"); | |
| 487 | + "capabilities contact default list new password"); | |
| 466 | 488 | } |
| 467 | 489 | } |
| 468 | 490 | |
| 469 | 491 | /* |
| 470 | 492 | ** Attempt to set the user to zLogin |
| @@ -750,7 +772,7 @@ | ||
| 750 | 772 | @ <label><input type="checkbox" name="delall"> |
| 751 | 773 | @ Delete all entries</input></label> |
| 752 | 774 | @ <input type="submit" name="delallbtn" value="Delete"></input> |
| 753 | 775 | @ </form> |
| 754 | 776 | style_table_sorter(); |
| 755 | - style_footer(); | |
| 777 | + style_finish_page("access_log"); | |
| 756 | 778 | } |
| 757 | 779 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -335,10 +335,14 @@ | |
| 335 | ** |
| 336 | ** > fossil user capabilities USERNAME ?STRING? |
| 337 | ** |
| 338 | ** Query or set the capabilities for user USERNAME |
| 339 | ** |
| 340 | ** > fossil user default ?USERNAME? |
| 341 | ** |
| 342 | ** Query or set the default user. The default user is the |
| 343 | ** user for command-line interaction. |
| 344 | ** |
| @@ -458,13 +462,31 @@ | |
| 458 | g.argv[4], uid |
| 459 | ); |
| 460 | db_protect_pop(); |
| 461 | } |
| 462 | fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid)); |
| 463 | }else{ |
| 464 | fossil_fatal("user subcommand should be one of: " |
| 465 | "capabilities default list new password"); |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | /* |
| 470 | ** Attempt to set the user to zLogin |
| @@ -750,7 +772,7 @@ | |
| 750 | @ <label><input type="checkbox" name="delall"> |
| 751 | @ Delete all entries</input></label> |
| 752 | @ <input type="submit" name="delallbtn" value="Delete"></input> |
| 753 | @ </form> |
| 754 | style_table_sorter(); |
| 755 | style_footer(); |
| 756 | } |
| 757 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -335,10 +335,14 @@ | |
| 335 | ** |
| 336 | ** > fossil user capabilities USERNAME ?STRING? |
| 337 | ** |
| 338 | ** Query or set the capabilities for user USERNAME |
| 339 | ** |
| 340 | ** > fossil user contact USERNAME ?CONTACT-INFO? |
| 341 | ** |
| 342 | ** Query or set contact information for user USERNAME |
| 343 | ** |
| 344 | ** > fossil user default ?USERNAME? |
| 345 | ** |
| 346 | ** Query or set the default user. The default user is the |
| 347 | ** user for command-line interaction. |
| 348 | ** |
| @@ -458,13 +462,31 @@ | |
| 462 | g.argv[4], uid |
| 463 | ); |
| 464 | db_protect_pop(); |
| 465 | } |
| 466 | fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid)); |
| 467 | }else if( n>=2 && strncmp(g.argv[2], "contact", 2)==0 ){ |
| 468 | int uid; |
| 469 | if( g.argc!=4 && g.argc!=5 ){ |
| 470 | usage("contact USERNAME ?CONTACT-INFO?"); |
| 471 | } |
| 472 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]); |
| 473 | if( uid==0 ){ |
| 474 | fossil_fatal("no such user: %s", g.argv[3]); |
| 475 | } |
| 476 | if( g.argc==5 ){ |
| 477 | db_unprotect(PROTECT_USER); |
| 478 | db_multi_exec( |
| 479 | "UPDATE user SET info=%Q, mtime=now() WHERE uid=%d", |
| 480 | g.argv[4], uid |
| 481 | ); |
| 482 | db_protect_pop(); |
| 483 | } |
| 484 | fossil_print("%s\n", db_text(0, "SELECT info FROM user WHERE uid=%d", uid)); |
| 485 | }else{ |
| 486 | fossil_fatal("user subcommand should be one of: " |
| 487 | "capabilities contact default list new password"); |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | /* |
| 492 | ** Attempt to set the user to zLogin |
| @@ -750,7 +772,7 @@ | |
| 772 | @ <label><input type="checkbox" name="delall"> |
| 773 | @ Delete all entries</input></label> |
| 774 | @ <input type="submit" name="delallbtn" value="Delete"></input> |
| 775 | @ </form> |
| 776 | style_table_sorter(); |
| 777 | style_finish_page("access_log"); |
| 778 | } |
| 779 |
+5
-5
| --- src/webmail.c | ||
| +++ src/webmail.c | ||
| @@ -513,11 +513,11 @@ | ||
| 513 | 513 | style_submenu_element("Delete", "%s", |
| 514 | 514 | url_render(pUrl,"trash","1",zENum,"1")); |
| 515 | 515 | } |
| 516 | 516 | |
| 517 | 517 | db_end_transaction(0); |
| 518 | - style_footer(); | |
| 518 | + style_finish_page("webmail"); | |
| 519 | 519 | return; |
| 520 | 520 | } |
| 521 | 521 | |
| 522 | 522 | /* |
| 523 | 523 | ** Scan the query parameters looking for parameters with name of the |
| @@ -613,11 +613,11 @@ | ||
| 613 | 613 | return; |
| 614 | 614 | } |
| 615 | 615 | if( !db_table_exists("repository","emailbox") ){ |
| 616 | 616 | style_header("Webmail Not Available"); |
| 617 | 617 | @ <p>This repository is not configured to provide webmail</p> |
| 618 | - style_footer(); | |
| 618 | + style_finish_page("webmail"); | |
| 619 | 619 | return; |
| 620 | 620 | } |
| 621 | 621 | add_content_sql_commands(g.db); |
| 622 | 622 | emailid = atoi(PD("id","0")); |
| 623 | 623 | url_initialize(&url, "webmail"); |
| @@ -757,11 +757,11 @@ | ||
| 757 | 757 | @ for(i=0; i<x.length; i++){ |
| 758 | 758 | @ x[i].checked = true; |
| 759 | 759 | @ } |
| 760 | 760 | @ } |
| 761 | 761 | @ </script> |
| 762 | - style_footer(); | |
| 762 | + style_finish_page("webmail"); | |
| 763 | 763 | db_end_transaction(0); |
| 764 | 764 | } |
| 765 | 765 | |
| 766 | 766 | /* |
| 767 | 767 | ** WEBPAGE: emailblob |
| @@ -854,11 +854,11 @@ | ||
| 854 | 854 | } |
| 855 | 855 | @ </tbody></table> |
| 856 | 856 | db_finalize(&q); |
| 857 | 857 | style_table_sorter(); |
| 858 | 858 | } |
| 859 | - style_footer(); | |
| 859 | + style_finish_page("webmail"); | |
| 860 | 860 | } |
| 861 | 861 | |
| 862 | 862 | /* |
| 863 | 863 | ** WEBPAGE: emailoutq |
| 864 | 864 | ** |
| @@ -911,7 +911,7 @@ | ||
| 911 | 911 | } |
| 912 | 912 | } |
| 913 | 913 | @ </tbody></table> |
| 914 | 914 | db_finalize(&q); |
| 915 | 915 | style_table_sorter(); |
| 916 | - style_footer(); | |
| 916 | + style_finish_page("webmail"); | |
| 917 | 917 | } |
| 918 | 918 |
| --- src/webmail.c | |
| +++ src/webmail.c | |
| @@ -513,11 +513,11 @@ | |
| 513 | style_submenu_element("Delete", "%s", |
| 514 | url_render(pUrl,"trash","1",zENum,"1")); |
| 515 | } |
| 516 | |
| 517 | db_end_transaction(0); |
| 518 | style_footer(); |
| 519 | return; |
| 520 | } |
| 521 | |
| 522 | /* |
| 523 | ** Scan the query parameters looking for parameters with name of the |
| @@ -613,11 +613,11 @@ | |
| 613 | return; |
| 614 | } |
| 615 | if( !db_table_exists("repository","emailbox") ){ |
| 616 | style_header("Webmail Not Available"); |
| 617 | @ <p>This repository is not configured to provide webmail</p> |
| 618 | style_footer(); |
| 619 | return; |
| 620 | } |
| 621 | add_content_sql_commands(g.db); |
| 622 | emailid = atoi(PD("id","0")); |
| 623 | url_initialize(&url, "webmail"); |
| @@ -757,11 +757,11 @@ | |
| 757 | @ for(i=0; i<x.length; i++){ |
| 758 | @ x[i].checked = true; |
| 759 | @ } |
| 760 | @ } |
| 761 | @ </script> |
| 762 | style_footer(); |
| 763 | db_end_transaction(0); |
| 764 | } |
| 765 | |
| 766 | /* |
| 767 | ** WEBPAGE: emailblob |
| @@ -854,11 +854,11 @@ | |
| 854 | } |
| 855 | @ </tbody></table> |
| 856 | db_finalize(&q); |
| 857 | style_table_sorter(); |
| 858 | } |
| 859 | style_footer(); |
| 860 | } |
| 861 | |
| 862 | /* |
| 863 | ** WEBPAGE: emailoutq |
| 864 | ** |
| @@ -911,7 +911,7 @@ | |
| 911 | } |
| 912 | } |
| 913 | @ </tbody></table> |
| 914 | db_finalize(&q); |
| 915 | style_table_sorter(); |
| 916 | style_footer(); |
| 917 | } |
| 918 |
| --- src/webmail.c | |
| +++ src/webmail.c | |
| @@ -513,11 +513,11 @@ | |
| 513 | style_submenu_element("Delete", "%s", |
| 514 | url_render(pUrl,"trash","1",zENum,"1")); |
| 515 | } |
| 516 | |
| 517 | db_end_transaction(0); |
| 518 | style_finish_page("webmail"); |
| 519 | return; |
| 520 | } |
| 521 | |
| 522 | /* |
| 523 | ** Scan the query parameters looking for parameters with name of the |
| @@ -613,11 +613,11 @@ | |
| 613 | return; |
| 614 | } |
| 615 | if( !db_table_exists("repository","emailbox") ){ |
| 616 | style_header("Webmail Not Available"); |
| 617 | @ <p>This repository is not configured to provide webmail</p> |
| 618 | style_finish_page("webmail"); |
| 619 | return; |
| 620 | } |
| 621 | add_content_sql_commands(g.db); |
| 622 | emailid = atoi(PD("id","0")); |
| 623 | url_initialize(&url, "webmail"); |
| @@ -757,11 +757,11 @@ | |
| 757 | @ for(i=0; i<x.length; i++){ |
| 758 | @ x[i].checked = true; |
| 759 | @ } |
| 760 | @ } |
| 761 | @ </script> |
| 762 | style_finish_page("webmail"); |
| 763 | db_end_transaction(0); |
| 764 | } |
| 765 | |
| 766 | /* |
| 767 | ** WEBPAGE: emailblob |
| @@ -854,11 +854,11 @@ | |
| 854 | } |
| 855 | @ </tbody></table> |
| 856 | db_finalize(&q); |
| 857 | style_table_sorter(); |
| 858 | } |
| 859 | style_finish_page("webmail"); |
| 860 | } |
| 861 | |
| 862 | /* |
| 863 | ** WEBPAGE: emailoutq |
| 864 | ** |
| @@ -911,7 +911,7 @@ | |
| 911 | } |
| 912 | } |
| 913 | @ </tbody></table> |
| 914 | db_finalize(&q); |
| 915 | style_table_sorter(); |
| 916 | style_finish_page("webmail"); |
| 917 | } |
| 918 |
+15
-15
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | if( !wiki_name_is_wellformed((const unsigned char *)z) ){ |
| 67 | 67 | style_header("Wiki Page Name Error"); |
| 68 | 68 | @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. |
| 69 | 69 | @ Rules for wiki page names: |
| 70 | 70 | well_formed_wiki_name_rules(); |
| 71 | - style_footer(); | |
| 71 | + style_finish_page("wiki"); | |
| 72 | 72 | return 1; |
| 73 | 73 | } |
| 74 | 74 | return 0; |
| 75 | 75 | } |
| 76 | 76 | |
| @@ -141,11 +141,11 @@ | ||
| 141 | 141 | @ To fill in this page, first go to |
| 142 | 142 | @ %z(href("%R/setup_config"))setup/config</a> |
| 143 | 143 | @ and establish a "Project Name". Then create a |
| 144 | 144 | @ wiki page with that name. The content of that wiki page |
| 145 | 145 | @ will be displayed in place of this message.</p> |
| 146 | - style_footer(); | |
| 146 | + style_finish_page("wiki"); | |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | /* |
| 150 | 150 | ** Return true if the given pagename is the name of the sandbox |
| 151 | 151 | */ |
| @@ -242,11 +242,11 @@ | ||
| 242 | 242 | blob_materialize(&x); |
| 243 | 243 | interwiki_append_map_table(&x); |
| 244 | 244 | safe_html_context(DOCSRC_TRUSTED); |
| 245 | 245 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 246 | 246 | blob_reset(&x); |
| 247 | - style_footer(); | |
| 247 | + style_finish_page("wiki"); | |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | /* |
| 251 | 251 | ** WEBPAGE: wiki_rules |
| 252 | 252 | ** |
| @@ -266,11 +266,11 @@ | ||
| 266 | 266 | blob_materialize(&x); |
| 267 | 267 | interwiki_append_map_table(&x); |
| 268 | 268 | safe_html_context(DOCSRC_TRUSTED); |
| 269 | 269 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 270 | 270 | blob_reset(&x); |
| 271 | - style_footer(); | |
| 271 | + style_finish_page("wiki"); | |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | 274 | /* |
| 275 | 275 | ** WEBPAGE: markup_help |
| 276 | 276 | ** |
| @@ -280,11 +280,11 @@ | ||
| 280 | 280 | style_header("Fossil Markup Styles"); |
| 281 | 281 | @ <ul> |
| 282 | 282 | @ <li><p>%z(href("%R/wiki_rules"))Fossil Wiki Formatting Rules</a></p></li> |
| 283 | 283 | @ <li><p>%z(href("%R/md_rules"))Markdown Formatting Rules</a></p></li> |
| 284 | 284 | @ </ul> |
| 285 | - style_footer(); | |
| 285 | + style_finish_page("wiki"); | |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | 288 | /* |
| 289 | 289 | ** Returns non-zero if moderation is required for wiki changes and wiki |
| 290 | 290 | ** attachments. |
| @@ -369,11 +369,11 @@ | ||
| 369 | 369 | if( search_restrict(SRCH_WIKI)!=0 ){ |
| 370 | 370 | @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key |
| 371 | 371 | @ words</li> |
| 372 | 372 | } |
| 373 | 373 | @ </ul> |
| 374 | - style_footer(); | |
| 374 | + style_finish_page("wiki"); | |
| 375 | 375 | return; |
| 376 | 376 | } |
| 377 | 377 | |
| 378 | 378 | /* |
| 379 | 379 | ** WEBPAGE: wikisrch |
| @@ -384,11 +384,11 @@ | ||
| 384 | 384 | void wiki_srchpage(void){ |
| 385 | 385 | login_check_credentials(); |
| 386 | 386 | style_header("Wiki Search"); |
| 387 | 387 | wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX); |
| 388 | 388 | search_screen(SRCH_WIKI, 0); |
| 389 | - style_footer(); | |
| 389 | + style_finish_page("wiki"); | |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | 392 | /* Return values from wiki_page_type() */ |
| 393 | 393 | #if INTERFACE |
| 394 | 394 | # define WIKITYPE_UNKNOWN (-1) |
| @@ -597,11 +597,11 @@ | ||
| 597 | 597 | blob_reset(&wiki); |
| 598 | 598 | } |
| 599 | 599 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 600 | 600 | manifest_destroy(pWiki); |
| 601 | 601 | document_emit_js(/*for optional pikchr support*/); |
| 602 | - style_footer(); | |
| 602 | + style_finish_page("wiki"); | |
| 603 | 603 | } |
| 604 | 604 | |
| 605 | 605 | /* |
| 606 | 606 | ** Write a wiki artifact into the repository |
| 607 | 607 | */ |
| @@ -1344,11 +1344,11 @@ | ||
| 1344 | 1344 | CX("}catch(e){" |
| 1345 | 1345 | "fossil.error(e); console.error('Exception:',e);" |
| 1346 | 1346 | "}\n"); |
| 1347 | 1347 | CX("});\n"/*fossil.onPageLoad()*/); |
| 1348 | 1348 | style_script_end(); |
| 1349 | - style_footer(); | |
| 1349 | + style_finish_page("wiki"); | |
| 1350 | 1350 | } |
| 1351 | 1351 | |
| 1352 | 1352 | /* |
| 1353 | 1353 | ** WEBPAGE: wikinew |
| 1354 | 1354 | ** URL /wikinew |
| @@ -1382,11 +1382,11 @@ | ||
| 1382 | 1382 | @ </p></form> |
| 1383 | 1383 | if( zName[0] ){ |
| 1384 | 1384 | @ <p><span class="wikiError"> |
| 1385 | 1385 | @ "%h(zName)" is not a valid wiki page name!</span></p> |
| 1386 | 1386 | } |
| 1387 | - style_footer(); | |
| 1387 | + style_finish_page("wiki"); | |
| 1388 | 1388 | } |
| 1389 | 1389 | |
| 1390 | 1390 | |
| 1391 | 1391 | /* |
| 1392 | 1392 | ** Append the wiki text for an remark to the end of the given BLOB. |
| @@ -1544,11 +1544,11 @@ | ||
| 1544 | 1544 | @ <input type="submit" name="preview" value="Preview Your Comment" /> |
| 1545 | 1545 | @ <input type="submit" name="submit" value="Append Your Changes" /> |
| 1546 | 1546 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 1547 | 1547 | captcha_generate(0); |
| 1548 | 1548 | @ </form> |
| 1549 | - style_footer(); | |
| 1549 | + style_finish_page("wiki"); | |
| 1550 | 1550 | } |
| 1551 | 1551 | |
| 1552 | 1552 | /* |
| 1553 | 1553 | ** WEBPAGE: whistory |
| 1554 | 1554 | ** URL: /whistory?name=PAGENAME |
| @@ -1634,11 +1634,11 @@ | ||
| 1634 | 1634 | } |
| 1635 | 1635 | @ </tbody></table></div> |
| 1636 | 1636 | db_finalize(&q); |
| 1637 | 1637 | builtin_request_js("fossil.page.whistory.js"); |
| 1638 | 1638 | /* style_table_sorter(); */ |
| 1639 | - style_footer(); | |
| 1639 | + style_finish_page("wiki"); | |
| 1640 | 1640 | } |
| 1641 | 1641 | |
| 1642 | 1642 | /* |
| 1643 | 1643 | ** WEBPAGE: wdiff |
| 1644 | 1644 | ** |
| @@ -1706,11 +1706,11 @@ | ||
| 1706 | 1706 | @ <pre class="udiff"> |
| 1707 | 1707 | @ %s(blob_str(&d)) |
| 1708 | 1708 | @ <pre> |
| 1709 | 1709 | manifest_destroy(pW1); |
| 1710 | 1710 | manifest_destroy(pW2); |
| 1711 | - style_footer(); | |
| 1711 | + style_finish_page("wiki"); | |
| 1712 | 1712 | } |
| 1713 | 1713 | |
| 1714 | 1714 | /* |
| 1715 | 1715 | ** A query that returns information about all wiki pages. |
| 1716 | 1716 | ** |
| @@ -1808,11 +1808,11 @@ | ||
| 1808 | 1808 | fossil_free(zWDisplayName); |
| 1809 | 1809 | } |
| 1810 | 1810 | @ </tbody></table></div> |
| 1811 | 1811 | db_finalize(&q); |
| 1812 | 1812 | style_table_sorter(); |
| 1813 | - style_footer(); | |
| 1813 | + style_finish_page("wiki"); | |
| 1814 | 1814 | } |
| 1815 | 1815 | |
| 1816 | 1816 | /* |
| 1817 | 1817 | ** WEBPAGE: wfind |
| 1818 | 1818 | ** |
| @@ -1835,11 +1835,11 @@ | ||
| 1835 | 1835 | const char *zName = db_column_text(&q, 0); |
| 1836 | 1836 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 1837 | 1837 | } |
| 1838 | 1838 | db_finalize(&q); |
| 1839 | 1839 | @ </ul> |
| 1840 | - style_footer(); | |
| 1840 | + style_finish_page("wiki"); | |
| 1841 | 1841 | } |
| 1842 | 1842 | |
| 1843 | 1843 | /* |
| 1844 | 1844 | ** Add a new wiki page to the repository. The page name is |
| 1845 | 1845 | ** given by the zPageName parameter. rid must be zero to create |
| 1846 | 1846 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | if( !wiki_name_is_wellformed((const unsigned char *)z) ){ |
| 67 | style_header("Wiki Page Name Error"); |
| 68 | @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. |
| 69 | @ Rules for wiki page names: |
| 70 | well_formed_wiki_name_rules(); |
| 71 | style_footer(); |
| 72 | return 1; |
| 73 | } |
| 74 | return 0; |
| 75 | } |
| 76 | |
| @@ -141,11 +141,11 @@ | |
| 141 | @ To fill in this page, first go to |
| 142 | @ %z(href("%R/setup_config"))setup/config</a> |
| 143 | @ and establish a "Project Name". Then create a |
| 144 | @ wiki page with that name. The content of that wiki page |
| 145 | @ will be displayed in place of this message.</p> |
| 146 | style_footer(); |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | ** Return true if the given pagename is the name of the sandbox |
| 151 | */ |
| @@ -242,11 +242,11 @@ | |
| 242 | blob_materialize(&x); |
| 243 | interwiki_append_map_table(&x); |
| 244 | safe_html_context(DOCSRC_TRUSTED); |
| 245 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 246 | blob_reset(&x); |
| 247 | style_footer(); |
| 248 | } |
| 249 | |
| 250 | /* |
| 251 | ** WEBPAGE: wiki_rules |
| 252 | ** |
| @@ -266,11 +266,11 @@ | |
| 266 | blob_materialize(&x); |
| 267 | interwiki_append_map_table(&x); |
| 268 | safe_html_context(DOCSRC_TRUSTED); |
| 269 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 270 | blob_reset(&x); |
| 271 | style_footer(); |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | ** WEBPAGE: markup_help |
| 276 | ** |
| @@ -280,11 +280,11 @@ | |
| 280 | style_header("Fossil Markup Styles"); |
| 281 | @ <ul> |
| 282 | @ <li><p>%z(href("%R/wiki_rules"))Fossil Wiki Formatting Rules</a></p></li> |
| 283 | @ <li><p>%z(href("%R/md_rules"))Markdown Formatting Rules</a></p></li> |
| 284 | @ </ul> |
| 285 | style_footer(); |
| 286 | } |
| 287 | |
| 288 | /* |
| 289 | ** Returns non-zero if moderation is required for wiki changes and wiki |
| 290 | ** attachments. |
| @@ -369,11 +369,11 @@ | |
| 369 | if( search_restrict(SRCH_WIKI)!=0 ){ |
| 370 | @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key |
| 371 | @ words</li> |
| 372 | } |
| 373 | @ </ul> |
| 374 | style_footer(); |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | /* |
| 379 | ** WEBPAGE: wikisrch |
| @@ -384,11 +384,11 @@ | |
| 384 | void wiki_srchpage(void){ |
| 385 | login_check_credentials(); |
| 386 | style_header("Wiki Search"); |
| 387 | wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX); |
| 388 | search_screen(SRCH_WIKI, 0); |
| 389 | style_footer(); |
| 390 | } |
| 391 | |
| 392 | /* Return values from wiki_page_type() */ |
| 393 | #if INTERFACE |
| 394 | # define WIKITYPE_UNKNOWN (-1) |
| @@ -597,11 +597,11 @@ | |
| 597 | blob_reset(&wiki); |
| 598 | } |
| 599 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 600 | manifest_destroy(pWiki); |
| 601 | document_emit_js(/*for optional pikchr support*/); |
| 602 | style_footer(); |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | ** Write a wiki artifact into the repository |
| 607 | */ |
| @@ -1344,11 +1344,11 @@ | |
| 1344 | CX("}catch(e){" |
| 1345 | "fossil.error(e); console.error('Exception:',e);" |
| 1346 | "}\n"); |
| 1347 | CX("});\n"/*fossil.onPageLoad()*/); |
| 1348 | style_script_end(); |
| 1349 | style_footer(); |
| 1350 | } |
| 1351 | |
| 1352 | /* |
| 1353 | ** WEBPAGE: wikinew |
| 1354 | ** URL /wikinew |
| @@ -1382,11 +1382,11 @@ | |
| 1382 | @ </p></form> |
| 1383 | if( zName[0] ){ |
| 1384 | @ <p><span class="wikiError"> |
| 1385 | @ "%h(zName)" is not a valid wiki page name!</span></p> |
| 1386 | } |
| 1387 | style_footer(); |
| 1388 | } |
| 1389 | |
| 1390 | |
| 1391 | /* |
| 1392 | ** Append the wiki text for an remark to the end of the given BLOB. |
| @@ -1544,11 +1544,11 @@ | |
| 1544 | @ <input type="submit" name="preview" value="Preview Your Comment" /> |
| 1545 | @ <input type="submit" name="submit" value="Append Your Changes" /> |
| 1546 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 1547 | captcha_generate(0); |
| 1548 | @ </form> |
| 1549 | style_footer(); |
| 1550 | } |
| 1551 | |
| 1552 | /* |
| 1553 | ** WEBPAGE: whistory |
| 1554 | ** URL: /whistory?name=PAGENAME |
| @@ -1634,11 +1634,11 @@ | |
| 1634 | } |
| 1635 | @ </tbody></table></div> |
| 1636 | db_finalize(&q); |
| 1637 | builtin_request_js("fossil.page.whistory.js"); |
| 1638 | /* style_table_sorter(); */ |
| 1639 | style_footer(); |
| 1640 | } |
| 1641 | |
| 1642 | /* |
| 1643 | ** WEBPAGE: wdiff |
| 1644 | ** |
| @@ -1706,11 +1706,11 @@ | |
| 1706 | @ <pre class="udiff"> |
| 1707 | @ %s(blob_str(&d)) |
| 1708 | @ <pre> |
| 1709 | manifest_destroy(pW1); |
| 1710 | manifest_destroy(pW2); |
| 1711 | style_footer(); |
| 1712 | } |
| 1713 | |
| 1714 | /* |
| 1715 | ** A query that returns information about all wiki pages. |
| 1716 | ** |
| @@ -1808,11 +1808,11 @@ | |
| 1808 | fossil_free(zWDisplayName); |
| 1809 | } |
| 1810 | @ </tbody></table></div> |
| 1811 | db_finalize(&q); |
| 1812 | style_table_sorter(); |
| 1813 | style_footer(); |
| 1814 | } |
| 1815 | |
| 1816 | /* |
| 1817 | ** WEBPAGE: wfind |
| 1818 | ** |
| @@ -1835,11 +1835,11 @@ | |
| 1835 | const char *zName = db_column_text(&q, 0); |
| 1836 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 1837 | } |
| 1838 | db_finalize(&q); |
| 1839 | @ </ul> |
| 1840 | style_footer(); |
| 1841 | } |
| 1842 | |
| 1843 | /* |
| 1844 | ** Add a new wiki page to the repository. The page name is |
| 1845 | ** given by the zPageName parameter. rid must be zero to create |
| 1846 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | if( !wiki_name_is_wellformed((const unsigned char *)z) ){ |
| 67 | style_header("Wiki Page Name Error"); |
| 68 | @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. |
| 69 | @ Rules for wiki page names: |
| 70 | well_formed_wiki_name_rules(); |
| 71 | style_finish_page("wiki"); |
| 72 | return 1; |
| 73 | } |
| 74 | return 0; |
| 75 | } |
| 76 | |
| @@ -141,11 +141,11 @@ | |
| 141 | @ To fill in this page, first go to |
| 142 | @ %z(href("%R/setup_config"))setup/config</a> |
| 143 | @ and establish a "Project Name". Then create a |
| 144 | @ wiki page with that name. The content of that wiki page |
| 145 | @ will be displayed in place of this message.</p> |
| 146 | style_finish_page("wiki"); |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | ** Return true if the given pagename is the name of the sandbox |
| 151 | */ |
| @@ -242,11 +242,11 @@ | |
| 242 | blob_materialize(&x); |
| 243 | interwiki_append_map_table(&x); |
| 244 | safe_html_context(DOCSRC_TRUSTED); |
| 245 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 246 | blob_reset(&x); |
| 247 | style_finish_page("wiki"); |
| 248 | } |
| 249 | |
| 250 | /* |
| 251 | ** WEBPAGE: wiki_rules |
| 252 | ** |
| @@ -266,11 +266,11 @@ | |
| 266 | blob_materialize(&x); |
| 267 | interwiki_append_map_table(&x); |
| 268 | safe_html_context(DOCSRC_TRUSTED); |
| 269 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 270 | blob_reset(&x); |
| 271 | style_finish_page("wiki"); |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | ** WEBPAGE: markup_help |
| 276 | ** |
| @@ -280,11 +280,11 @@ | |
| 280 | style_header("Fossil Markup Styles"); |
| 281 | @ <ul> |
| 282 | @ <li><p>%z(href("%R/wiki_rules"))Fossil Wiki Formatting Rules</a></p></li> |
| 283 | @ <li><p>%z(href("%R/md_rules"))Markdown Formatting Rules</a></p></li> |
| 284 | @ </ul> |
| 285 | style_finish_page("wiki"); |
| 286 | } |
| 287 | |
| 288 | /* |
| 289 | ** Returns non-zero if moderation is required for wiki changes and wiki |
| 290 | ** attachments. |
| @@ -369,11 +369,11 @@ | |
| 369 | if( search_restrict(SRCH_WIKI)!=0 ){ |
| 370 | @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key |
| 371 | @ words</li> |
| 372 | } |
| 373 | @ </ul> |
| 374 | style_finish_page("wiki"); |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | /* |
| 379 | ** WEBPAGE: wikisrch |
| @@ -384,11 +384,11 @@ | |
| 384 | void wiki_srchpage(void){ |
| 385 | login_check_credentials(); |
| 386 | style_header("Wiki Search"); |
| 387 | wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX); |
| 388 | search_screen(SRCH_WIKI, 0); |
| 389 | style_finish_page("wiki"); |
| 390 | } |
| 391 | |
| 392 | /* Return values from wiki_page_type() */ |
| 393 | #if INTERFACE |
| 394 | # define WIKITYPE_UNKNOWN (-1) |
| @@ -597,11 +597,11 @@ | |
| 597 | blob_reset(&wiki); |
| 598 | } |
| 599 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 600 | manifest_destroy(pWiki); |
| 601 | document_emit_js(/*for optional pikchr support*/); |
| 602 | style_finish_page("wiki"); |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | ** Write a wiki artifact into the repository |
| 607 | */ |
| @@ -1344,11 +1344,11 @@ | |
| 1344 | CX("}catch(e){" |
| 1345 | "fossil.error(e); console.error('Exception:',e);" |
| 1346 | "}\n"); |
| 1347 | CX("});\n"/*fossil.onPageLoad()*/); |
| 1348 | style_script_end(); |
| 1349 | style_finish_page("wiki"); |
| 1350 | } |
| 1351 | |
| 1352 | /* |
| 1353 | ** WEBPAGE: wikinew |
| 1354 | ** URL /wikinew |
| @@ -1382,11 +1382,11 @@ | |
| 1382 | @ </p></form> |
| 1383 | if( zName[0] ){ |
| 1384 | @ <p><span class="wikiError"> |
| 1385 | @ "%h(zName)" is not a valid wiki page name!</span></p> |
| 1386 | } |
| 1387 | style_finish_page("wiki"); |
| 1388 | } |
| 1389 | |
| 1390 | |
| 1391 | /* |
| 1392 | ** Append the wiki text for an remark to the end of the given BLOB. |
| @@ -1544,11 +1544,11 @@ | |
| 1544 | @ <input type="submit" name="preview" value="Preview Your Comment" /> |
| 1545 | @ <input type="submit" name="submit" value="Append Your Changes" /> |
| 1546 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 1547 | captcha_generate(0); |
| 1548 | @ </form> |
| 1549 | style_finish_page("wiki"); |
| 1550 | } |
| 1551 | |
| 1552 | /* |
| 1553 | ** WEBPAGE: whistory |
| 1554 | ** URL: /whistory?name=PAGENAME |
| @@ -1634,11 +1634,11 @@ | |
| 1634 | } |
| 1635 | @ </tbody></table></div> |
| 1636 | db_finalize(&q); |
| 1637 | builtin_request_js("fossil.page.whistory.js"); |
| 1638 | /* style_table_sorter(); */ |
| 1639 | style_finish_page("wiki"); |
| 1640 | } |
| 1641 | |
| 1642 | /* |
| 1643 | ** WEBPAGE: wdiff |
| 1644 | ** |
| @@ -1706,11 +1706,11 @@ | |
| 1706 | @ <pre class="udiff"> |
| 1707 | @ %s(blob_str(&d)) |
| 1708 | @ <pre> |
| 1709 | manifest_destroy(pW1); |
| 1710 | manifest_destroy(pW2); |
| 1711 | style_finish_page("wiki"); |
| 1712 | } |
| 1713 | |
| 1714 | /* |
| 1715 | ** A query that returns information about all wiki pages. |
| 1716 | ** |
| @@ -1808,11 +1808,11 @@ | |
| 1808 | fossil_free(zWDisplayName); |
| 1809 | } |
| 1810 | @ </tbody></table></div> |
| 1811 | db_finalize(&q); |
| 1812 | style_table_sorter(); |
| 1813 | style_finish_page("wiki"); |
| 1814 | } |
| 1815 | |
| 1816 | /* |
| 1817 | ** WEBPAGE: wfind |
| 1818 | ** |
| @@ -1835,11 +1835,11 @@ | |
| 1835 | const char *zName = db_column_text(&q, 0); |
| 1836 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 1837 | } |
| 1838 | db_finalize(&q); |
| 1839 | @ </ul> |
| 1840 | style_finish_page("wiki"); |
| 1841 | } |
| 1842 | |
| 1843 | /* |
| 1844 | ** Add a new wiki page to the repository. The page name is |
| 1845 | ** given by the zPageName parameter. rid must be zero to create |
| 1846 |
+15
-15
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | if( !wiki_name_is_wellformed((const unsigned char *)z) ){ |
| 67 | 67 | style_header("Wiki Page Name Error"); |
| 68 | 68 | @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. |
| 69 | 69 | @ Rules for wiki page names: |
| 70 | 70 | well_formed_wiki_name_rules(); |
| 71 | - style_footer(); | |
| 71 | + style_finish_page("wiki"); | |
| 72 | 72 | return 1; |
| 73 | 73 | } |
| 74 | 74 | return 0; |
| 75 | 75 | } |
| 76 | 76 | |
| @@ -141,11 +141,11 @@ | ||
| 141 | 141 | @ To fill in this page, first go to |
| 142 | 142 | @ %z(href("%R/setup_config"))setup/config</a> |
| 143 | 143 | @ and establish a "Project Name". Then create a |
| 144 | 144 | @ wiki page with that name. The content of that wiki page |
| 145 | 145 | @ will be displayed in place of this message.</p> |
| 146 | - style_footer(); | |
| 146 | + style_finish_page("wiki"); | |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | /* |
| 150 | 150 | ** Return true if the given pagename is the name of the sandbox |
| 151 | 151 | */ |
| @@ -242,11 +242,11 @@ | ||
| 242 | 242 | blob_materialize(&x); |
| 243 | 243 | interwiki_append_map_table(&x); |
| 244 | 244 | safe_html_context(DOCSRC_TRUSTED); |
| 245 | 245 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 246 | 246 | blob_reset(&x); |
| 247 | - style_footer(); | |
| 247 | + style_finish_page("wiki"); | |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | /* |
| 251 | 251 | ** WEBPAGE: wiki_rules |
| 252 | 252 | ** |
| @@ -266,11 +266,11 @@ | ||
| 266 | 266 | blob_materialize(&x); |
| 267 | 267 | interwiki_append_map_table(&x); |
| 268 | 268 | safe_html_context(DOCSRC_TRUSTED); |
| 269 | 269 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 270 | 270 | blob_reset(&x); |
| 271 | - style_footer(); | |
| 271 | + style_finish_page("wiki"); | |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | 274 | /* |
| 275 | 275 | ** WEBPAGE: markup_help |
| 276 | 276 | ** |
| @@ -280,11 +280,11 @@ | ||
| 280 | 280 | style_header("Fossil Markup Styles"); |
| 281 | 281 | @ <ul> |
| 282 | 282 | @ <li><p>%z(href("%R/wiki_rules"))Fossil Wiki Formatting Rules</a></p></li> |
| 283 | 283 | @ <li><p>%z(href("%R/md_rules"))Markdown Formatting Rules</a></p></li> |
| 284 | 284 | @ </ul> |
| 285 | - style_footer(); | |
| 285 | + style_finish_page("wiki"); | |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | 288 | /* |
| 289 | 289 | ** Returns non-zero if moderation is required for wiki changes and wiki |
| 290 | 290 | ** attachments. |
| @@ -369,11 +369,11 @@ | ||
| 369 | 369 | if( search_restrict(SRCH_WIKI)!=0 ){ |
| 370 | 370 | @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key |
| 371 | 371 | @ words</li> |
| 372 | 372 | } |
| 373 | 373 | @ </ul> |
| 374 | - style_footer(); | |
| 374 | + style_finish_page("wiki"); | |
| 375 | 375 | return; |
| 376 | 376 | } |
| 377 | 377 | |
| 378 | 378 | /* |
| 379 | 379 | ** WEBPAGE: wikisrch |
| @@ -384,11 +384,11 @@ | ||
| 384 | 384 | void wiki_srchpage(void){ |
| 385 | 385 | login_check_credentials(); |
| 386 | 386 | style_header("Wiki Search"); |
| 387 | 387 | wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX); |
| 388 | 388 | search_screen(SRCH_WIKI, 0); |
| 389 | - style_footer(); | |
| 389 | + style_finish_page("wiki"); | |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | 392 | /* Return values from wiki_page_type() */ |
| 393 | 393 | #if INTERFACE |
| 394 | 394 | # define WIKITYPE_UNKNOWN (-1) |
| @@ -597,11 +597,11 @@ | ||
| 597 | 597 | blob_reset(&wiki); |
| 598 | 598 | } |
| 599 | 599 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 600 | 600 | manifest_destroy(pWiki); |
| 601 | 601 | document_emit_js(/*for optional pikchr support*/); |
| 602 | - style_footer(); | |
| 602 | + style_finish_page("wiki"); | |
| 603 | 603 | } |
| 604 | 604 | |
| 605 | 605 | /* |
| 606 | 606 | ** Write a wiki artifact into the repository |
| 607 | 607 | */ |
| @@ -1344,11 +1344,11 @@ | ||
| 1344 | 1344 | CX("}catch(e){" |
| 1345 | 1345 | "fossil.error(e); console.error('Exception:',e);" |
| 1346 | 1346 | "}\n"); |
| 1347 | 1347 | CX("});\n"/*fossil.onPageLoad()*/); |
| 1348 | 1348 | style_script_end(); |
| 1349 | - style_footer(); | |
| 1349 | + style_finish_page("wiki"); | |
| 1350 | 1350 | } |
| 1351 | 1351 | |
| 1352 | 1352 | /* |
| 1353 | 1353 | ** WEBPAGE: wikinew |
| 1354 | 1354 | ** URL /wikinew |
| @@ -1382,11 +1382,11 @@ | ||
| 1382 | 1382 | @ </p></form> |
| 1383 | 1383 | if( zName[0] ){ |
| 1384 | 1384 | @ <p><span class="wikiError"> |
| 1385 | 1385 | @ "%h(zName)" is not a valid wiki page name!</span></p> |
| 1386 | 1386 | } |
| 1387 | - style_footer(); | |
| 1387 | + style_finish_page("wiki"); | |
| 1388 | 1388 | } |
| 1389 | 1389 | |
| 1390 | 1390 | |
| 1391 | 1391 | /* |
| 1392 | 1392 | ** Append the wiki text for an remark to the end of the given BLOB. |
| @@ -1544,11 +1544,11 @@ | ||
| 1544 | 1544 | @ <input type="submit" name="preview" value="Preview Your Comment" /> |
| 1545 | 1545 | @ <input type="submit" name="submit" value="Append Your Changes" /> |
| 1546 | 1546 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 1547 | 1547 | captcha_generate(0); |
| 1548 | 1548 | @ </form> |
| 1549 | - style_footer(); | |
| 1549 | + style_finish_page("wiki"); | |
| 1550 | 1550 | } |
| 1551 | 1551 | |
| 1552 | 1552 | /* |
| 1553 | 1553 | ** WEBPAGE: whistory |
| 1554 | 1554 | ** URL: /whistory?name=PAGENAME |
| @@ -1634,11 +1634,11 @@ | ||
| 1634 | 1634 | } |
| 1635 | 1635 | @ </tbody></table></div> |
| 1636 | 1636 | db_finalize(&q); |
| 1637 | 1637 | builtin_request_js("fossil.page.whistory.js"); |
| 1638 | 1638 | /* style_table_sorter(); */ |
| 1639 | - style_footer(); | |
| 1639 | + style_finish_page("wiki"); | |
| 1640 | 1640 | } |
| 1641 | 1641 | |
| 1642 | 1642 | /* |
| 1643 | 1643 | ** WEBPAGE: wdiff |
| 1644 | 1644 | ** |
| @@ -1706,11 +1706,11 @@ | ||
| 1706 | 1706 | @ <pre class="udiff"> |
| 1707 | 1707 | @ %s(blob_str(&d)) |
| 1708 | 1708 | @ <pre> |
| 1709 | 1709 | manifest_destroy(pW1); |
| 1710 | 1710 | manifest_destroy(pW2); |
| 1711 | - style_footer(); | |
| 1711 | + style_finish_page("wiki"); | |
| 1712 | 1712 | } |
| 1713 | 1713 | |
| 1714 | 1714 | /* |
| 1715 | 1715 | ** A query that returns information about all wiki pages. |
| 1716 | 1716 | ** |
| @@ -1808,11 +1808,11 @@ | ||
| 1808 | 1808 | fossil_free(zWDisplayName); |
| 1809 | 1809 | } |
| 1810 | 1810 | @ </tbody></table></div> |
| 1811 | 1811 | db_finalize(&q); |
| 1812 | 1812 | style_table_sorter(); |
| 1813 | - style_footer(); | |
| 1813 | + style_finish_page("wiki"); | |
| 1814 | 1814 | } |
| 1815 | 1815 | |
| 1816 | 1816 | /* |
| 1817 | 1817 | ** WEBPAGE: wfind |
| 1818 | 1818 | ** |
| @@ -1835,11 +1835,11 @@ | ||
| 1835 | 1835 | const char *zName = db_column_text(&q, 0); |
| 1836 | 1836 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 1837 | 1837 | } |
| 1838 | 1838 | db_finalize(&q); |
| 1839 | 1839 | @ </ul> |
| 1840 | - style_footer(); | |
| 1840 | + style_finish_page("wiki"); | |
| 1841 | 1841 | } |
| 1842 | 1842 | |
| 1843 | 1843 | /* |
| 1844 | 1844 | ** Add a new wiki page to the repository. The page name is |
| 1845 | 1845 | ** given by the zPageName parameter. rid must be zero to create |
| 1846 | 1846 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | if( !wiki_name_is_wellformed((const unsigned char *)z) ){ |
| 67 | style_header("Wiki Page Name Error"); |
| 68 | @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. |
| 69 | @ Rules for wiki page names: |
| 70 | well_formed_wiki_name_rules(); |
| 71 | style_footer(); |
| 72 | return 1; |
| 73 | } |
| 74 | return 0; |
| 75 | } |
| 76 | |
| @@ -141,11 +141,11 @@ | |
| 141 | @ To fill in this page, first go to |
| 142 | @ %z(href("%R/setup_config"))setup/config</a> |
| 143 | @ and establish a "Project Name". Then create a |
| 144 | @ wiki page with that name. The content of that wiki page |
| 145 | @ will be displayed in place of this message.</p> |
| 146 | style_footer(); |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | ** Return true if the given pagename is the name of the sandbox |
| 151 | */ |
| @@ -242,11 +242,11 @@ | |
| 242 | blob_materialize(&x); |
| 243 | interwiki_append_map_table(&x); |
| 244 | safe_html_context(DOCSRC_TRUSTED); |
| 245 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 246 | blob_reset(&x); |
| 247 | style_footer(); |
| 248 | } |
| 249 | |
| 250 | /* |
| 251 | ** WEBPAGE: wiki_rules |
| 252 | ** |
| @@ -266,11 +266,11 @@ | |
| 266 | blob_materialize(&x); |
| 267 | interwiki_append_map_table(&x); |
| 268 | safe_html_context(DOCSRC_TRUSTED); |
| 269 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 270 | blob_reset(&x); |
| 271 | style_footer(); |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | ** WEBPAGE: markup_help |
| 276 | ** |
| @@ -280,11 +280,11 @@ | |
| 280 | style_header("Fossil Markup Styles"); |
| 281 | @ <ul> |
| 282 | @ <li><p>%z(href("%R/wiki_rules"))Fossil Wiki Formatting Rules</a></p></li> |
| 283 | @ <li><p>%z(href("%R/md_rules"))Markdown Formatting Rules</a></p></li> |
| 284 | @ </ul> |
| 285 | style_footer(); |
| 286 | } |
| 287 | |
| 288 | /* |
| 289 | ** Returns non-zero if moderation is required for wiki changes and wiki |
| 290 | ** attachments. |
| @@ -369,11 +369,11 @@ | |
| 369 | if( search_restrict(SRCH_WIKI)!=0 ){ |
| 370 | @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key |
| 371 | @ words</li> |
| 372 | } |
| 373 | @ </ul> |
| 374 | style_footer(); |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | /* |
| 379 | ** WEBPAGE: wikisrch |
| @@ -384,11 +384,11 @@ | |
| 384 | void wiki_srchpage(void){ |
| 385 | login_check_credentials(); |
| 386 | style_header("Wiki Search"); |
| 387 | wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX); |
| 388 | search_screen(SRCH_WIKI, 0); |
| 389 | style_footer(); |
| 390 | } |
| 391 | |
| 392 | /* Return values from wiki_page_type() */ |
| 393 | #if INTERFACE |
| 394 | # define WIKITYPE_UNKNOWN (-1) |
| @@ -597,11 +597,11 @@ | |
| 597 | blob_reset(&wiki); |
| 598 | } |
| 599 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 600 | manifest_destroy(pWiki); |
| 601 | document_emit_js(/*for optional pikchr support*/); |
| 602 | style_footer(); |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | ** Write a wiki artifact into the repository |
| 607 | */ |
| @@ -1344,11 +1344,11 @@ | |
| 1344 | CX("}catch(e){" |
| 1345 | "fossil.error(e); console.error('Exception:',e);" |
| 1346 | "}\n"); |
| 1347 | CX("});\n"/*fossil.onPageLoad()*/); |
| 1348 | style_script_end(); |
| 1349 | style_footer(); |
| 1350 | } |
| 1351 | |
| 1352 | /* |
| 1353 | ** WEBPAGE: wikinew |
| 1354 | ** URL /wikinew |
| @@ -1382,11 +1382,11 @@ | |
| 1382 | @ </p></form> |
| 1383 | if( zName[0] ){ |
| 1384 | @ <p><span class="wikiError"> |
| 1385 | @ "%h(zName)" is not a valid wiki page name!</span></p> |
| 1386 | } |
| 1387 | style_footer(); |
| 1388 | } |
| 1389 | |
| 1390 | |
| 1391 | /* |
| 1392 | ** Append the wiki text for an remark to the end of the given BLOB. |
| @@ -1544,11 +1544,11 @@ | |
| 1544 | @ <input type="submit" name="preview" value="Preview Your Comment" /> |
| 1545 | @ <input type="submit" name="submit" value="Append Your Changes" /> |
| 1546 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 1547 | captcha_generate(0); |
| 1548 | @ </form> |
| 1549 | style_footer(); |
| 1550 | } |
| 1551 | |
| 1552 | /* |
| 1553 | ** WEBPAGE: whistory |
| 1554 | ** URL: /whistory?name=PAGENAME |
| @@ -1634,11 +1634,11 @@ | |
| 1634 | } |
| 1635 | @ </tbody></table></div> |
| 1636 | db_finalize(&q); |
| 1637 | builtin_request_js("fossil.page.whistory.js"); |
| 1638 | /* style_table_sorter(); */ |
| 1639 | style_footer(); |
| 1640 | } |
| 1641 | |
| 1642 | /* |
| 1643 | ** WEBPAGE: wdiff |
| 1644 | ** |
| @@ -1706,11 +1706,11 @@ | |
| 1706 | @ <pre class="udiff"> |
| 1707 | @ %s(blob_str(&d)) |
| 1708 | @ <pre> |
| 1709 | manifest_destroy(pW1); |
| 1710 | manifest_destroy(pW2); |
| 1711 | style_footer(); |
| 1712 | } |
| 1713 | |
| 1714 | /* |
| 1715 | ** A query that returns information about all wiki pages. |
| 1716 | ** |
| @@ -1808,11 +1808,11 @@ | |
| 1808 | fossil_free(zWDisplayName); |
| 1809 | } |
| 1810 | @ </tbody></table></div> |
| 1811 | db_finalize(&q); |
| 1812 | style_table_sorter(); |
| 1813 | style_footer(); |
| 1814 | } |
| 1815 | |
| 1816 | /* |
| 1817 | ** WEBPAGE: wfind |
| 1818 | ** |
| @@ -1835,11 +1835,11 @@ | |
| 1835 | const char *zName = db_column_text(&q, 0); |
| 1836 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 1837 | } |
| 1838 | db_finalize(&q); |
| 1839 | @ </ul> |
| 1840 | style_footer(); |
| 1841 | } |
| 1842 | |
| 1843 | /* |
| 1844 | ** Add a new wiki page to the repository. The page name is |
| 1845 | ** given by the zPageName parameter. rid must be zero to create |
| 1846 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | if( !wiki_name_is_wellformed((const unsigned char *)z) ){ |
| 67 | style_header("Wiki Page Name Error"); |
| 68 | @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. |
| 69 | @ Rules for wiki page names: |
| 70 | well_formed_wiki_name_rules(); |
| 71 | style_finish_page("wiki"); |
| 72 | return 1; |
| 73 | } |
| 74 | return 0; |
| 75 | } |
| 76 | |
| @@ -141,11 +141,11 @@ | |
| 141 | @ To fill in this page, first go to |
| 142 | @ %z(href("%R/setup_config"))setup/config</a> |
| 143 | @ and establish a "Project Name". Then create a |
| 144 | @ wiki page with that name. The content of that wiki page |
| 145 | @ will be displayed in place of this message.</p> |
| 146 | style_finish_page("wiki"); |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | ** Return true if the given pagename is the name of the sandbox |
| 151 | */ |
| @@ -242,11 +242,11 @@ | |
| 242 | blob_materialize(&x); |
| 243 | interwiki_append_map_table(&x); |
| 244 | safe_html_context(DOCSRC_TRUSTED); |
| 245 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown"); |
| 246 | blob_reset(&x); |
| 247 | style_finish_page("wiki"); |
| 248 | } |
| 249 | |
| 250 | /* |
| 251 | ** WEBPAGE: wiki_rules |
| 252 | ** |
| @@ -266,11 +266,11 @@ | |
| 266 | blob_materialize(&x); |
| 267 | interwiki_append_map_table(&x); |
| 268 | safe_html_context(DOCSRC_TRUSTED); |
| 269 | wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-fossil-wiki"); |
| 270 | blob_reset(&x); |
| 271 | style_finish_page("wiki"); |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | ** WEBPAGE: markup_help |
| 276 | ** |
| @@ -280,11 +280,11 @@ | |
| 280 | style_header("Fossil Markup Styles"); |
| 281 | @ <ul> |
| 282 | @ <li><p>%z(href("%R/wiki_rules"))Fossil Wiki Formatting Rules</a></p></li> |
| 283 | @ <li><p>%z(href("%R/md_rules"))Markdown Formatting Rules</a></p></li> |
| 284 | @ </ul> |
| 285 | style_finish_page("wiki"); |
| 286 | } |
| 287 | |
| 288 | /* |
| 289 | ** Returns non-zero if moderation is required for wiki changes and wiki |
| 290 | ** attachments. |
| @@ -369,11 +369,11 @@ | |
| 369 | if( search_restrict(SRCH_WIKI)!=0 ){ |
| 370 | @ <li> %z(href("%R/wikisrch"))Search</a> for wiki pages containing key |
| 371 | @ words</li> |
| 372 | } |
| 373 | @ </ul> |
| 374 | style_finish_page("wiki"); |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | /* |
| 379 | ** WEBPAGE: wikisrch |
| @@ -384,11 +384,11 @@ | |
| 384 | void wiki_srchpage(void){ |
| 385 | login_check_credentials(); |
| 386 | style_header("Wiki Search"); |
| 387 | wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX); |
| 388 | search_screen(SRCH_WIKI, 0); |
| 389 | style_finish_page("wiki"); |
| 390 | } |
| 391 | |
| 392 | /* Return values from wiki_page_type() */ |
| 393 | #if INTERFACE |
| 394 | # define WIKITYPE_UNKNOWN (-1) |
| @@ -597,11 +597,11 @@ | |
| 597 | blob_reset(&wiki); |
| 598 | } |
| 599 | attachment_list(zPageName, "<hr /><h2>Attachments:</h2><ul>"); |
| 600 | manifest_destroy(pWiki); |
| 601 | document_emit_js(/*for optional pikchr support*/); |
| 602 | style_finish_page("wiki"); |
| 603 | } |
| 604 | |
| 605 | /* |
| 606 | ** Write a wiki artifact into the repository |
| 607 | */ |
| @@ -1344,11 +1344,11 @@ | |
| 1344 | CX("}catch(e){" |
| 1345 | "fossil.error(e); console.error('Exception:',e);" |
| 1346 | "}\n"); |
| 1347 | CX("});\n"/*fossil.onPageLoad()*/); |
| 1348 | style_script_end(); |
| 1349 | style_finish_page("wiki"); |
| 1350 | } |
| 1351 | |
| 1352 | /* |
| 1353 | ** WEBPAGE: wikinew |
| 1354 | ** URL /wikinew |
| @@ -1382,11 +1382,11 @@ | |
| 1382 | @ </p></form> |
| 1383 | if( zName[0] ){ |
| 1384 | @ <p><span class="wikiError"> |
| 1385 | @ "%h(zName)" is not a valid wiki page name!</span></p> |
| 1386 | } |
| 1387 | style_finish_page("wiki"); |
| 1388 | } |
| 1389 | |
| 1390 | |
| 1391 | /* |
| 1392 | ** Append the wiki text for an remark to the end of the given BLOB. |
| @@ -1544,11 +1544,11 @@ | |
| 1544 | @ <input type="submit" name="preview" value="Preview Your Comment" /> |
| 1545 | @ <input type="submit" name="submit" value="Append Your Changes" /> |
| 1546 | @ <input type="submit" name="cancel" value="Cancel" /> |
| 1547 | captcha_generate(0); |
| 1548 | @ </form> |
| 1549 | style_finish_page("wiki"); |
| 1550 | } |
| 1551 | |
| 1552 | /* |
| 1553 | ** WEBPAGE: whistory |
| 1554 | ** URL: /whistory?name=PAGENAME |
| @@ -1634,11 +1634,11 @@ | |
| 1634 | } |
| 1635 | @ </tbody></table></div> |
| 1636 | db_finalize(&q); |
| 1637 | builtin_request_js("fossil.page.whistory.js"); |
| 1638 | /* style_table_sorter(); */ |
| 1639 | style_finish_page("wiki"); |
| 1640 | } |
| 1641 | |
| 1642 | /* |
| 1643 | ** WEBPAGE: wdiff |
| 1644 | ** |
| @@ -1706,11 +1706,11 @@ | |
| 1706 | @ <pre class="udiff"> |
| 1707 | @ %s(blob_str(&d)) |
| 1708 | @ <pre> |
| 1709 | manifest_destroy(pW1); |
| 1710 | manifest_destroy(pW2); |
| 1711 | style_finish_page("wiki"); |
| 1712 | } |
| 1713 | |
| 1714 | /* |
| 1715 | ** A query that returns information about all wiki pages. |
| 1716 | ** |
| @@ -1808,11 +1808,11 @@ | |
| 1808 | fossil_free(zWDisplayName); |
| 1809 | } |
| 1810 | @ </tbody></table></div> |
| 1811 | db_finalize(&q); |
| 1812 | style_table_sorter(); |
| 1813 | style_finish_page("wiki"); |
| 1814 | } |
| 1815 | |
| 1816 | /* |
| 1817 | ** WEBPAGE: wfind |
| 1818 | ** |
| @@ -1835,11 +1835,11 @@ | |
| 1835 | const char *zName = db_column_text(&q, 0); |
| 1836 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 1837 | } |
| 1838 | db_finalize(&q); |
| 1839 | @ </ul> |
| 1840 | style_finish_page("wiki"); |
| 1841 | } |
| 1842 | |
| 1843 | /* |
| 1844 | ** Add a new wiki page to the repository. The page name is |
| 1845 | ** given by the zPageName parameter. rid must be zero to create |
| 1846 |
+18
-15
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -63,10 +63,11 @@ | ||
| 63 | 63 | ATTR_SIZE, |
| 64 | 64 | ATTR_SRC, |
| 65 | 65 | ATTR_START, |
| 66 | 66 | ATTR_STYLE, |
| 67 | 67 | ATTR_TARGET, |
| 68 | + ATTR_TITLE, | |
| 68 | 69 | ATTR_TYPE, |
| 69 | 70 | ATTR_VALIGN, |
| 70 | 71 | ATTR_VALUE, |
| 71 | 72 | ATTR_VSPACE, |
| 72 | 73 | ATTR_WIDTH |
| @@ -82,24 +83,24 @@ | ||
| 82 | 83 | AMSK_CLASS = 0x00000040, |
| 83 | 84 | AMSK_CLEAR = 0x00000080, |
| 84 | 85 | AMSK_COLOR = 0x00000100, |
| 85 | 86 | AMSK_COLSPAN = 0x00000200, |
| 86 | 87 | AMSK_COMPACT = 0x00000400, |
| 87 | - /* re-use = 0x00000800, */ | |
| 88 | - AMSK_FACE = 0x00001000, | |
| 89 | - AMSK_HEIGHT = 0x00002000, | |
| 90 | - AMSK_HREF = 0x00004000, | |
| 91 | - AMSK_HSPACE = 0x00008000, | |
| 92 | - AMSK_ID = 0x00010000, | |
| 93 | - AMSK_LINKS = 0x00020000, | |
| 94 | - AMSK_NAME = 0x00040000, | |
| 95 | - AMSK_ROWSPAN = 0x00080000, | |
| 96 | - AMSK_SIZE = 0x00100000, | |
| 97 | - AMSK_SRC = 0x00200000, | |
| 98 | - AMSK_START = 0x00400000, | |
| 99 | - AMSK_STYLE = 0x00800000, | |
| 100 | - AMSK_TARGET = 0x01000000, | |
| 88 | + AMSK_FACE = 0x00000800, | |
| 89 | + AMSK_HEIGHT = 0x00001000, | |
| 90 | + AMSK_HREF = 0x00002000, | |
| 91 | + AMSK_HSPACE = 0x00004000, | |
| 92 | + AMSK_ID = 0x00008000, | |
| 93 | + AMSK_LINKS = 0x00010000, | |
| 94 | + AMSK_NAME = 0x00020000, | |
| 95 | + AMSK_ROWSPAN = 0x00040000, | |
| 96 | + AMSK_SIZE = 0x00080000, | |
| 97 | + AMSK_SRC = 0x00100000, | |
| 98 | + AMSK_START = 0x00200000, | |
| 99 | + AMSK_STYLE = 0x00400000, | |
| 100 | + AMSK_TARGET = 0x00800000, | |
| 101 | + AMSK_TITLE = 0x01000000, | |
| 101 | 102 | AMSK_TYPE = 0x02000000, |
| 102 | 103 | AMSK_VALIGN = 0x04000000, |
| 103 | 104 | AMSK_VALUE = 0x08000000, |
| 104 | 105 | AMSK_VSPACE = 0x10000000, |
| 105 | 106 | AMSK_WIDTH = 0x20000000 |
| @@ -135,10 +136,11 @@ | ||
| 135 | 136 | { "size", AMSK_SIZE }, |
| 136 | 137 | { "src", AMSK_SRC }, |
| 137 | 138 | { "start", AMSK_START }, |
| 138 | 139 | { "style", AMSK_STYLE }, |
| 139 | 140 | { "target", AMSK_TARGET }, |
| 141 | + { "title", AMSK_TITLE }, | |
| 140 | 142 | { "type", AMSK_TYPE }, |
| 141 | 143 | { "valign", AMSK_VALIGN }, |
| 142 | 144 | { "value", AMSK_VALUE }, |
| 143 | 145 | { "vspace", AMSK_VSPACE }, |
| 144 | 146 | { "width", AMSK_WIDTH }, |
| @@ -273,11 +275,12 @@ | ||
| 273 | 275 | short int iType; /* The MUTYPE_* code */ |
| 274 | 276 | int allowedAttr; /* Allowed attributes on this markup */ |
| 275 | 277 | } aMarkup[] = { |
| 276 | 278 | { 0, MARKUP_INVALID, 0, 0 }, |
| 277 | 279 | { "a", MARKUP_A, MUTYPE_HYPERLINK, |
| 278 | - AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE }, | |
| 280 | + AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE| | |
| 281 | + AMSK_TITLE}, | |
| 279 | 282 | { "address", MARKUP_ADDRESS, MUTYPE_BLOCK, AMSK_STYLE }, |
| 280 | 283 | { "article", MARKUP_HTML5_ARTICLE, MUTYPE_BLOCK, |
| 281 | 284 | AMSK_ID|AMSK_CLASS|AMSK_STYLE }, |
| 282 | 285 | { "aside", MARKUP_HTML5_ASIDE, MUTYPE_BLOCK, |
| 283 | 286 | AMSK_ID|AMSK_CLASS|AMSK_STYLE }, |
| 284 | 287 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -63,10 +63,11 @@ | |
| 63 | ATTR_SIZE, |
| 64 | ATTR_SRC, |
| 65 | ATTR_START, |
| 66 | ATTR_STYLE, |
| 67 | ATTR_TARGET, |
| 68 | ATTR_TYPE, |
| 69 | ATTR_VALIGN, |
| 70 | ATTR_VALUE, |
| 71 | ATTR_VSPACE, |
| 72 | ATTR_WIDTH |
| @@ -82,24 +83,24 @@ | |
| 82 | AMSK_CLASS = 0x00000040, |
| 83 | AMSK_CLEAR = 0x00000080, |
| 84 | AMSK_COLOR = 0x00000100, |
| 85 | AMSK_COLSPAN = 0x00000200, |
| 86 | AMSK_COMPACT = 0x00000400, |
| 87 | /* re-use = 0x00000800, */ |
| 88 | AMSK_FACE = 0x00001000, |
| 89 | AMSK_HEIGHT = 0x00002000, |
| 90 | AMSK_HREF = 0x00004000, |
| 91 | AMSK_HSPACE = 0x00008000, |
| 92 | AMSK_ID = 0x00010000, |
| 93 | AMSK_LINKS = 0x00020000, |
| 94 | AMSK_NAME = 0x00040000, |
| 95 | AMSK_ROWSPAN = 0x00080000, |
| 96 | AMSK_SIZE = 0x00100000, |
| 97 | AMSK_SRC = 0x00200000, |
| 98 | AMSK_START = 0x00400000, |
| 99 | AMSK_STYLE = 0x00800000, |
| 100 | AMSK_TARGET = 0x01000000, |
| 101 | AMSK_TYPE = 0x02000000, |
| 102 | AMSK_VALIGN = 0x04000000, |
| 103 | AMSK_VALUE = 0x08000000, |
| 104 | AMSK_VSPACE = 0x10000000, |
| 105 | AMSK_WIDTH = 0x20000000 |
| @@ -135,10 +136,11 @@ | |
| 135 | { "size", AMSK_SIZE }, |
| 136 | { "src", AMSK_SRC }, |
| 137 | { "start", AMSK_START }, |
| 138 | { "style", AMSK_STYLE }, |
| 139 | { "target", AMSK_TARGET }, |
| 140 | { "type", AMSK_TYPE }, |
| 141 | { "valign", AMSK_VALIGN }, |
| 142 | { "value", AMSK_VALUE }, |
| 143 | { "vspace", AMSK_VSPACE }, |
| 144 | { "width", AMSK_WIDTH }, |
| @@ -273,11 +275,12 @@ | |
| 273 | short int iType; /* The MUTYPE_* code */ |
| 274 | int allowedAttr; /* Allowed attributes on this markup */ |
| 275 | } aMarkup[] = { |
| 276 | { 0, MARKUP_INVALID, 0, 0 }, |
| 277 | { "a", MARKUP_A, MUTYPE_HYPERLINK, |
| 278 | AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE }, |
| 279 | { "address", MARKUP_ADDRESS, MUTYPE_BLOCK, AMSK_STYLE }, |
| 280 | { "article", MARKUP_HTML5_ARTICLE, MUTYPE_BLOCK, |
| 281 | AMSK_ID|AMSK_CLASS|AMSK_STYLE }, |
| 282 | { "aside", MARKUP_HTML5_ASIDE, MUTYPE_BLOCK, |
| 283 | AMSK_ID|AMSK_CLASS|AMSK_STYLE }, |
| 284 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -63,10 +63,11 @@ | |
| 63 | ATTR_SIZE, |
| 64 | ATTR_SRC, |
| 65 | ATTR_START, |
| 66 | ATTR_STYLE, |
| 67 | ATTR_TARGET, |
| 68 | ATTR_TITLE, |
| 69 | ATTR_TYPE, |
| 70 | ATTR_VALIGN, |
| 71 | ATTR_VALUE, |
| 72 | ATTR_VSPACE, |
| 73 | ATTR_WIDTH |
| @@ -82,24 +83,24 @@ | |
| 83 | AMSK_CLASS = 0x00000040, |
| 84 | AMSK_CLEAR = 0x00000080, |
| 85 | AMSK_COLOR = 0x00000100, |
| 86 | AMSK_COLSPAN = 0x00000200, |
| 87 | AMSK_COMPACT = 0x00000400, |
| 88 | AMSK_FACE = 0x00000800, |
| 89 | AMSK_HEIGHT = 0x00001000, |
| 90 | AMSK_HREF = 0x00002000, |
| 91 | AMSK_HSPACE = 0x00004000, |
| 92 | AMSK_ID = 0x00008000, |
| 93 | AMSK_LINKS = 0x00010000, |
| 94 | AMSK_NAME = 0x00020000, |
| 95 | AMSK_ROWSPAN = 0x00040000, |
| 96 | AMSK_SIZE = 0x00080000, |
| 97 | AMSK_SRC = 0x00100000, |
| 98 | AMSK_START = 0x00200000, |
| 99 | AMSK_STYLE = 0x00400000, |
| 100 | AMSK_TARGET = 0x00800000, |
| 101 | AMSK_TITLE = 0x01000000, |
| 102 | AMSK_TYPE = 0x02000000, |
| 103 | AMSK_VALIGN = 0x04000000, |
| 104 | AMSK_VALUE = 0x08000000, |
| 105 | AMSK_VSPACE = 0x10000000, |
| 106 | AMSK_WIDTH = 0x20000000 |
| @@ -135,10 +136,11 @@ | |
| 136 | { "size", AMSK_SIZE }, |
| 137 | { "src", AMSK_SRC }, |
| 138 | { "start", AMSK_START }, |
| 139 | { "style", AMSK_STYLE }, |
| 140 | { "target", AMSK_TARGET }, |
| 141 | { "title", AMSK_TITLE }, |
| 142 | { "type", AMSK_TYPE }, |
| 143 | { "valign", AMSK_VALIGN }, |
| 144 | { "value", AMSK_VALUE }, |
| 145 | { "vspace", AMSK_VSPACE }, |
| 146 | { "width", AMSK_WIDTH }, |
| @@ -273,11 +275,12 @@ | |
| 275 | short int iType; /* The MUTYPE_* code */ |
| 276 | int allowedAttr; /* Allowed attributes on this markup */ |
| 277 | } aMarkup[] = { |
| 278 | { 0, MARKUP_INVALID, 0, 0 }, |
| 279 | { "a", MARKUP_A, MUTYPE_HYPERLINK, |
| 280 | AMSK_HREF|AMSK_NAME|AMSK_CLASS|AMSK_TARGET|AMSK_STYLE| |
| 281 | AMSK_TITLE}, |
| 282 | { "address", MARKUP_ADDRESS, MUTYPE_BLOCK, AMSK_STYLE }, |
| 283 | { "article", MARKUP_HTML5_ARTICLE, MUTYPE_BLOCK, |
| 284 | AMSK_ID|AMSK_CLASS|AMSK_STYLE }, |
| 285 | { "aside", MARKUP_HTML5_ASIDE, MUTYPE_BLOCK, |
| 286 | AMSK_ID|AMSK_CLASS|AMSK_STYLE }, |
| 287 |
+2
-2
| --- src/xfersetup.c | ||
| +++ src/xfersetup.c | ||
| @@ -85,11 +85,11 @@ | ||
| 85 | 85 | client_sync(syncFlags, 0, 0, 0); |
| 86 | 86 | @ </pre> |
| 87 | 87 | } |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | - style_footer(); | |
| 90 | + style_finish_page("xfersetup"); | |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | /* |
| 94 | 94 | ** Common implementation for the transfer setup editor pages. |
| 95 | 95 | */ |
| @@ -150,11 +150,11 @@ | ||
| 150 | 150 | @ <h2>Default %s(zTitle)</h2> |
| 151 | 151 | @ <blockquote><pre> |
| 152 | 152 | @ %h(zDfltValue) |
| 153 | 153 | @ </pre></blockquote> |
| 154 | 154 | } |
| 155 | - style_footer(); | |
| 155 | + style_finish_page("xfersetup"); | |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | 158 | static const char *zDefaultXferCommon = 0; |
| 159 | 159 | |
| 160 | 160 | /* |
| 161 | 161 |
| --- src/xfersetup.c | |
| +++ src/xfersetup.c | |
| @@ -85,11 +85,11 @@ | |
| 85 | client_sync(syncFlags, 0, 0, 0); |
| 86 | @ </pre> |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | style_footer(); |
| 91 | } |
| 92 | |
| 93 | /* |
| 94 | ** Common implementation for the transfer setup editor pages. |
| 95 | */ |
| @@ -150,11 +150,11 @@ | |
| 150 | @ <h2>Default %s(zTitle)</h2> |
| 151 | @ <blockquote><pre> |
| 152 | @ %h(zDfltValue) |
| 153 | @ </pre></blockquote> |
| 154 | } |
| 155 | style_footer(); |
| 156 | } |
| 157 | |
| 158 | static const char *zDefaultXferCommon = 0; |
| 159 | |
| 160 | /* |
| 161 |
| --- src/xfersetup.c | |
| +++ src/xfersetup.c | |
| @@ -85,11 +85,11 @@ | |
| 85 | client_sync(syncFlags, 0, 0, 0); |
| 86 | @ </pre> |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | style_finish_page("xfersetup"); |
| 91 | } |
| 92 | |
| 93 | /* |
| 94 | ** Common implementation for the transfer setup editor pages. |
| 95 | */ |
| @@ -150,11 +150,11 @@ | |
| 150 | @ <h2>Default %s(zTitle)</h2> |
| 151 | @ <blockquote><pre> |
| 152 | @ %h(zDfltValue) |
| 153 | @ </pre></blockquote> |
| 154 | } |
| 155 | style_finish_page("xfersetup"); |
| 156 | } |
| 157 | |
| 158 | static const char *zDefaultXferCommon = 0; |
| 159 | |
| 160 | /* |
| 161 |
+2
-2
| --- src/zip.c | ||
| +++ src/zip.c | ||
| @@ -955,11 +955,11 @@ | ||
| 955 | 955 | } |
| 956 | 956 | if( zExclude ){ |
| 957 | 957 | @ zExclude = "%h(zExclude)"<br /> |
| 958 | 958 | } |
| 959 | 959 | @ zKey = "%h(zKey)" |
| 960 | - style_footer(); | |
| 960 | + style_finish_page("zip"); | |
| 961 | 961 | return; |
| 962 | 962 | } |
| 963 | 963 | if( referred_from_login() ){ |
| 964 | 964 | style_header("%s Archive Download", zType); |
| 965 | 965 | @ <form action='%R/%s(g.zPath)/%h(zName).%s(g.zPath)'> |
| @@ -966,11 +966,11 @@ | ||
| 966 | 966 | cgi_query_parameters_to_hidden(); |
| 967 | 967 | @ <p>%s(zType) Archive named <b>%h(zName).%s(g.zPath)</b> |
| 968 | 968 | @ holding the content of check-in <b>%h(zRid)</b>: |
| 969 | 969 | @ <input type="submit" value="Download" /> |
| 970 | 970 | @ </form> |
| 971 | - style_footer(); | |
| 971 | + style_finish_page("zip"); | |
| 972 | 972 | return; |
| 973 | 973 | } |
| 974 | 974 | blob_zero(&zip); |
| 975 | 975 | if( cache_read(&zip, zKey)==0 ){ |
| 976 | 976 | zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); |
| 977 | 977 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -955,11 +955,11 @@ | |
| 955 | } |
| 956 | if( zExclude ){ |
| 957 | @ zExclude = "%h(zExclude)"<br /> |
| 958 | } |
| 959 | @ zKey = "%h(zKey)" |
| 960 | style_footer(); |
| 961 | return; |
| 962 | } |
| 963 | if( referred_from_login() ){ |
| 964 | style_header("%s Archive Download", zType); |
| 965 | @ <form action='%R/%s(g.zPath)/%h(zName).%s(g.zPath)'> |
| @@ -966,11 +966,11 @@ | |
| 966 | cgi_query_parameters_to_hidden(); |
| 967 | @ <p>%s(zType) Archive named <b>%h(zName).%s(g.zPath)</b> |
| 968 | @ holding the content of check-in <b>%h(zRid)</b>: |
| 969 | @ <input type="submit" value="Download" /> |
| 970 | @ </form> |
| 971 | style_footer(); |
| 972 | return; |
| 973 | } |
| 974 | blob_zero(&zip); |
| 975 | if( cache_read(&zip, zKey)==0 ){ |
| 976 | zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); |
| 977 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -955,11 +955,11 @@ | |
| 955 | } |
| 956 | if( zExclude ){ |
| 957 | @ zExclude = "%h(zExclude)"<br /> |
| 958 | } |
| 959 | @ zKey = "%h(zKey)" |
| 960 | style_finish_page("zip"); |
| 961 | return; |
| 962 | } |
| 963 | if( referred_from_login() ){ |
| 964 | style_header("%s Archive Download", zType); |
| 965 | @ <form action='%R/%s(g.zPath)/%h(zName).%s(g.zPath)'> |
| @@ -966,11 +966,11 @@ | |
| 966 | cgi_query_parameters_to_hidden(); |
| 967 | @ <p>%s(zType) Archive named <b>%h(zName).%s(g.zPath)</b> |
| 968 | @ holding the content of check-in <b>%h(zRid)</b>: |
| 969 | @ <input type="submit" value="Download" /> |
| 970 | @ </form> |
| 971 | style_finish_page("zip"); |
| 972 | return; |
| 973 | } |
| 974 | blob_zero(&zip); |
| 975 | if( cache_read(&zip, zKey)==0 ){ |
| 976 | zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude); |
| 977 |
+48
-40
| --- www/backup.md | ||
| +++ www/backup.md | ||
| @@ -1,11 +1,11 @@ | ||
| 1 | 1 | # Backing Up a Remote Fossil Repository |
| 2 | 2 | |
| 3 | 3 | One of the great benefits of Fossil and other [distributed version control systems][dvcs] |
| 4 | 4 | is that cloning a repository makes a backup. If you are running a project with multiple |
| 5 | 5 | developers who share their work using a [central server][server] and the server hardware |
| 6 | -catches fire or otherwise becomes unavailable, the clones of the repository on each developer | |
| 6 | +catches fire, the clones of the repository on each developer | |
| 7 | 7 | workstation *may* serve as a suitable backup. |
| 8 | 8 | |
| 9 | 9 | [dvcs]: wikipedia:/wiki/Distributed_version_control |
| 10 | 10 | [server]: ./server/whyuseaserver.wiki |
| 11 | 11 | |
| @@ -15,20 +15,20 @@ | ||
| 15 | 15 | that, a Fossil repository typically contains |
| 16 | 16 | other useful information that is not always shared as part of a clone, which might need |
| 17 | 17 | to be backed up separately. To wit: |
| 18 | 18 | |
| 19 | 19 | |
| 20 | -## Sensitive Information | |
| 20 | +## <a id="pii"></a> Sensitive Information | |
| 21 | 21 | |
| 22 | 22 | Fossil purposefully does not clone certain sensitive information unless |
| 23 | -you’re logged in as a user with [setup] capability. As an example, a local clone | |
| 23 | +you’re logged in as a user with [Setup] capability. As an example, a local clone | |
| 24 | 24 | may have a different `user` table than the remote, because only a |
| 25 | 25 | Setup user is allowed to see the full version for privacy and security |
| 26 | 26 | reasons. |
| 27 | 27 | |
| 28 | 28 | |
| 29 | -## Configuration Drift | |
| 29 | +## <a id="config"></a> Configuration Drift | |
| 30 | 30 | |
| 31 | 31 | Fossil allows the local configuration in certain areas to differ from |
| 32 | 32 | that of the remote. With the exception of the prior item, you get a copy |
| 33 | 33 | of these configuration areas on initial clone, but after that, some |
| 34 | 34 | remote configuration changes don’t sync down automatically, such as the |
| @@ -35,37 +35,37 @@ | ||
| 35 | 35 | remote’s skin. You can ask for updates by running the |
| 36 | 36 | [`fossil config pull skin`](./help?cmd=config) command, but that |
| 37 | 37 | does not happen automatically during the course of normal development. |
| 38 | 38 | |
| 39 | 39 | |
| 40 | -## Private Branches | |
| 40 | +## <a id="private"></a> Private Branches | |
| 41 | 41 | |
| 42 | 42 | The very nature of Fossil’s [private branch feature][pbr] ensures that |
| 43 | 43 | remote clones don’t get a copy of those branches. Normally this is |
| 44 | 44 | exactly what you want, but in the case of making backups, you probably |
| 45 | 45 | want to back up these branches as well. One of the two backup methods below |
| 46 | 46 | provides this. |
| 47 | 47 | |
| 48 | 48 | |
| 49 | -## Shunned Artifacts | |
| 49 | +## <a id="shun"></a> Shunned Artifacts | |
| 50 | 50 | |
| 51 | 51 | Fossil purposefully doesn’t sync [shunned artifacts][shun]. If you want |
| 52 | 52 | your local clone to be a precise match to the remote, it needs to track |
| 53 | 53 | changes to the shun table as well. |
| 54 | 54 | |
| 55 | 55 | |
| 56 | -## Unversioned Artifacts | |
| 56 | +## <a id="uv"></a> Unversioned Artifacts | |
| 57 | 57 | |
| 58 | 58 | Data in Fossil’s [unversioned artifacts table][uv] doesn’t sync down by |
| 59 | 59 | default unless you specifically ask for it. Like local configuration |
| 60 | 60 | data, it doesn’t get pulled as part of a normal `fossil sync`, but |
| 61 | 61 | *unlike* the config data, you don’t get unversioned files as part of the |
| 62 | 62 | initial clone unless you ask for it by passing the `--unversioned/-u` |
| 63 | 63 | flag. |
| 64 | 64 | |
| 65 | 65 | |
| 66 | -## Autosync Is Intransitive | |
| 66 | +## <a id="ait"></a>Autosync Is Intransitive | |
| 67 | 67 | |
| 68 | 68 | If you’re using Fossil in a truly distributed mode, rather than the |
| 69 | 69 | simple central-and-clones model that is more common, there may be no |
| 70 | 70 | single source of truth in the network because Fossil’s autosync feature |
| 71 | 71 | isn’t transitive. |
| @@ -92,11 +92,11 @@ | ||
| 92 | 92 | source of truth, those users still syncing with `svr2` won’t have their |
| 93 | 93 | commits pushed up to `svr1` unless you’ve set up bidirectional sync, |
| 94 | 94 | rather than have the two backup servers do `pull` only. |
| 95 | 95 | |
| 96 | 96 | |
| 97 | -# Solutions | |
| 97 | +# Solution 1: Explicit Pulls | |
| 98 | 98 | |
| 99 | 99 | The following script solves most of the above problems for the use case |
| 100 | 100 | where you want a *nearly-complete* clone of the remote repository using nothing |
| 101 | 101 | but the normal Fossil sync protocol. It only does so if you are logged into |
| 102 | 102 | the remote as a user with Setup capability, however. |
| @@ -118,11 +118,14 @@ | ||
| 118 | 118 | out of existence, your backup will be “more than complete” in the sense |
| 119 | 119 | that it will continue to have information that the remote says should |
| 120 | 120 | not exist any more. That would be not so much a “backup” as an |
| 121 | 121 | “archive,” which might not be what you want. |
| 122 | 122 | |
| 123 | -This method doesn’t get you a copy of the remote’s | |
| 123 | + | |
| 124 | +# Solution 2: SQL-Level Backup | |
| 125 | + | |
| 126 | +The first method doesn’t get you a copy of the remote’s | |
| 124 | 127 | [private branches][pbr], on purpose. It may also miss other info on the |
| 125 | 128 | remote, such as SQL-level customizations that the sync protocol can’t |
| 126 | 129 | see. (Some [ticket system customization][tkt] schemes rely on this ability, for example.) You can |
| 127 | 130 | solve such problems if you have access to the remote server, which |
| 128 | 131 | allows you to get a SQL-level backup. This requires Fossil 2.12 or |
| @@ -139,12 +142,20 @@ | ||
| 139 | 142 | bf=repo-$(date +%Y-%m-%d).fossil |
| 140 | 143 | ssh example.com "cd museum ; fossil backup -R repo.fossil backups/$bf" && |
| 141 | 144 | scp example.com:museum/backups/$bf ~/museum/backups |
| 142 | 145 | ``` |
| 143 | 146 | |
| 147 | +---- | |
| 148 | + | |
| 149 | +Beware that this method does not solve [the intransitive sync | |
| 150 | +problem](#ait), in and of itself: if you do a SQL-level backup of a | |
| 151 | +stale repo DB, you have a *stale backup!* You should therefore run this | |
| 152 | +on every node that may need to serve as a backup so that at least *one* | |
| 153 | +of the backups is also up-to-date. | |
| 154 | + | |
| 144 | 155 | |
| 145 | -## Encrypted Off-Site Backups | |
| 156 | +# <a id="enc"></a> Encrypted Off-Site Backups | |
| 146 | 157 | |
| 147 | 158 | A useful refinement that you can apply to both methods above is |
| 148 | 159 | encrypted off-site backups. You may wish to store backups of your |
| 149 | 160 | repositories off-site on a service such as Dropbox, Google Drive, iCloud, |
| 150 | 161 | or Microsoft OneDrive, where you don’t fully trust the service not to |
| @@ -165,24 +176,10 @@ | ||
| 165 | 176 | |
| 166 | 177 | If you’re adding this to the first script above, remove the |
| 167 | 178 | “`-R repo-name`” bit so you get a dump of the repository backing the |
| 168 | 179 | current working directory. |
| 169 | 180 | |
| 170 | -This requires OpenSSL 1.1 or higher. If you’re on 1.0 or older, you | |
| 171 | -won’t have the `-pbkdf2` and `-iter` options, and you may have to choose | |
| 172 | -a different cipher algorithm; both changes are likely to weaken the | |
| 173 | -encryption significantly, so you should install a newer version rather | |
| 174 | -than work around the lack of these features. | |
| 175 | - | |
| 176 | -If you’re on macOS, which | |
| 177 | -still ships 1.0 as of the time of this writing, [Homebrew][hb] offers | |
| 178 | -the current version of OpenSSL, but to avoid a conflict with the platform | |
| 179 | -version it’s [unlinked][hbul] by default, so you have to give an explicit | |
| 180 | -path to its “cellar” directory: | |
| 181 | - | |
| 182 | - /usr/local/Cellar/openssl\@1.1/1.1.1g/bin/openssl ... | |
| 183 | - | |
| 184 | 181 | Change the `pass` value to some other long random string, and change the |
| 185 | 182 | `iter` value to something between 10000 and 100000. A good source for |
| 186 | 183 | the first is [here][grcp], and for the second, [here][rint]. |
| 187 | 184 | |
| 188 | 185 | Compressing the data before encrypting it removes redundancies that can |
| @@ -192,21 +189,33 @@ | ||
| 192 | 189 | compression algorithm that takes less CPU power, such as [`lz4`][lz4]. |
| 193 | 190 | Changing up the compression algorithm also provides some |
| 194 | 191 | security-thru-obscurity, which is useless on its own, but it *is* a |
| 195 | 192 | useful adjunct to strong encryption. |
| 196 | 193 | |
| 194 | +This requires OpenSSL 1.1 or higher. If you’re on 1.0 or older, you | |
| 195 | +won’t have the `-pbkdf2` and `-iter` options, and you may have to choose | |
| 196 | +a different cipher algorithm; both changes are likely to weaken the | |
| 197 | +encryption significantly, so you should install a newer version rather | |
| 198 | +than work around the lack of these features. If you’re on macOS, which | |
| 199 | +still ships 1.0 as of the time of this writing, [Homebrew][hb] offers | |
| 200 | +the current version of OpenSSL, but to avoid a conflict with the platform | |
| 201 | +version, it’s [unlinked][hbul] by default, so you have to give an explicit | |
| 202 | +path to its “cellar” directory: | |
| 203 | + | |
| 204 | + /usr/local/Cellar/openssl\@1.1/1.1.1g/bin/openssl ... | |
| 205 | + | |
| 197 | 206 | |
| 198 | -## Restoring From An Encrypted Backup | |
| 207 | +## <a id="rest"></a> Restoring From An Encrypted Backup | |
| 199 | 208 | |
| 200 | 209 | The “restore” script for the above fragment is basically an inverse of |
| 201 | 210 | it, but it’s worth showing it because there are some subtleties to take |
| 202 | 211 | care of. If all variables defined in earlier scripts are available, then |
| 203 | 212 | restoration is: |
| 204 | 213 | |
| 205 | 214 | ``` |
| 206 | 215 | openssl enc -d -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -in "$gd" | |
| 207 | - xz -d | sqlite3 ~/museum/restored-repo.fossil | |
| 216 | + xz -d | fossil --no-repository ~/museum/restored-repo.fossil | |
| 208 | 217 | ``` |
| 209 | 218 | |
| 210 | 219 | We changed the `-e` to `-d` on the `openssl` command to get decryption, |
| 211 | 220 | and we changed the `-out` to `-in` so it reads from the encrypted backup |
| 212 | 221 | file and writes the result to stdout. |
| @@ -213,30 +222,29 @@ | ||
| 213 | 222 | |
| 214 | 223 | The decompression step is trivial. |
| 215 | 224 | |
| 216 | 225 | The last change is tricky: we used `fossil sql` above to ensure that |
| 217 | 226 | we’re using the same version of SQLite to write the encrypted backup DB |
| 218 | -as was used to maintain the repository, but unfortunately, we can’t get | |
| 219 | -the built-in SQLite shell to write a backup into an empty database. | |
| 220 | -(As soon as it starts up, it goes looking for tables created by | |
| 221 | -`fossil init` and fails with an error.) | |
| 222 | -Therefore, we have to either run the restoration against a | |
| 223 | -possibly-different version of SQLite and hope there are no | |
| 224 | -incompatibilities, or we have to go out of our way to build a matching | |
| 225 | -version of `sqlite3` before we can safely do the restoration. | |
| 226 | - | |
| 227 | -Keep in mind that Fossil often acts as a dogfooding project for SQLite, | |
| 228 | -making use of the latest features, so it is quite likely that a given | |
| 227 | +as was used to maintain the repository. We must also do that on | |
| 228 | +restoration: | |
| 229 | +Fossil serves as a dogfooding project for SQLite, | |
| 230 | +often making use of the latest features, so it is quite likely that a given | |
| 229 | 231 | random `sqlite3` binary in your `PATH` will be unable to understand the |
| 230 | -file created by “`fossil sql .dump`”! | |
| 232 | +file created by “`fossil sql .dump`”! The tricky bit is, you can’t just | |
| 233 | +pipe the decrpted SQL dump into `fossil sql`, because on startup, Fossil | |
| 234 | +normally goes looking for tables created by `fossil init`, and it won’t | |
| 235 | +find them in a newly-created repo DB. We get around this by passing | |
| 236 | +the `--no-repository` flag, which suppresses this behavior. Doing it | |
| 237 | +this way saves you from needing to go and build a matching version of | |
| 238 | +`sqlite3` just to restore the backup. | |
| 231 | 239 | |
| 232 | 240 | [bu]: /help?cmd=backup |
| 233 | 241 | [grcp]: https://www.grc.com/passwords.htm |
| 234 | 242 | [hb]: https://brew.sh |
| 235 | 243 | [hbul]: https://docs.brew.sh/FAQ#what-does-keg-only-mean |
| 236 | 244 | [lz4]: https://lz4.github.io/lz4/ |
| 237 | 245 | [pbr]: ./private.wiki |
| 238 | 246 | [rint]: https://www.random.org/integers/?num=1&min=10000&max=100000&col=5&base=10&format=html&rnd=new |
| 239 | -[setup]: ./caps/admin-v-setup.md#apsu | |
| 247 | +[Setup]: ./caps/admin-v-setup.md#apsu | |
| 240 | 248 | [shun]: ./shunning.wiki |
| 241 | 249 | [tkt]: ./tickets.wiki |
| 242 | 250 | [uv]: ./unvers.wiki |
| 243 | 251 |
| --- www/backup.md | |
| +++ www/backup.md | |
| @@ -1,11 +1,11 @@ | |
| 1 | # Backing Up a Remote Fossil Repository |
| 2 | |
| 3 | One of the great benefits of Fossil and other [distributed version control systems][dvcs] |
| 4 | is that cloning a repository makes a backup. If you are running a project with multiple |
| 5 | developers who share their work using a [central server][server] and the server hardware |
| 6 | catches fire or otherwise becomes unavailable, the clones of the repository on each developer |
| 7 | workstation *may* serve as a suitable backup. |
| 8 | |
| 9 | [dvcs]: wikipedia:/wiki/Distributed_version_control |
| 10 | [server]: ./server/whyuseaserver.wiki |
| 11 | |
| @@ -15,20 +15,20 @@ | |
| 15 | that, a Fossil repository typically contains |
| 16 | other useful information that is not always shared as part of a clone, which might need |
| 17 | to be backed up separately. To wit: |
| 18 | |
| 19 | |
| 20 | ## Sensitive Information |
| 21 | |
| 22 | Fossil purposefully does not clone certain sensitive information unless |
| 23 | you’re logged in as a user with [setup] capability. As an example, a local clone |
| 24 | may have a different `user` table than the remote, because only a |
| 25 | Setup user is allowed to see the full version for privacy and security |
| 26 | reasons. |
| 27 | |
| 28 | |
| 29 | ## Configuration Drift |
| 30 | |
| 31 | Fossil allows the local configuration in certain areas to differ from |
| 32 | that of the remote. With the exception of the prior item, you get a copy |
| 33 | of these configuration areas on initial clone, but after that, some |
| 34 | remote configuration changes don’t sync down automatically, such as the |
| @@ -35,37 +35,37 @@ | |
| 35 | remote’s skin. You can ask for updates by running the |
| 36 | [`fossil config pull skin`](./help?cmd=config) command, but that |
| 37 | does not happen automatically during the course of normal development. |
| 38 | |
| 39 | |
| 40 | ## Private Branches |
| 41 | |
| 42 | The very nature of Fossil’s [private branch feature][pbr] ensures that |
| 43 | remote clones don’t get a copy of those branches. Normally this is |
| 44 | exactly what you want, but in the case of making backups, you probably |
| 45 | want to back up these branches as well. One of the two backup methods below |
| 46 | provides this. |
| 47 | |
| 48 | |
| 49 | ## Shunned Artifacts |
| 50 | |
| 51 | Fossil purposefully doesn’t sync [shunned artifacts][shun]. If you want |
| 52 | your local clone to be a precise match to the remote, it needs to track |
| 53 | changes to the shun table as well. |
| 54 | |
| 55 | |
| 56 | ## Unversioned Artifacts |
| 57 | |
| 58 | Data in Fossil’s [unversioned artifacts table][uv] doesn’t sync down by |
| 59 | default unless you specifically ask for it. Like local configuration |
| 60 | data, it doesn’t get pulled as part of a normal `fossil sync`, but |
| 61 | *unlike* the config data, you don’t get unversioned files as part of the |
| 62 | initial clone unless you ask for it by passing the `--unversioned/-u` |
| 63 | flag. |
| 64 | |
| 65 | |
| 66 | ## Autosync Is Intransitive |
| 67 | |
| 68 | If you’re using Fossil in a truly distributed mode, rather than the |
| 69 | simple central-and-clones model that is more common, there may be no |
| 70 | single source of truth in the network because Fossil’s autosync feature |
| 71 | isn’t transitive. |
| @@ -92,11 +92,11 @@ | |
| 92 | source of truth, those users still syncing with `svr2` won’t have their |
| 93 | commits pushed up to `svr1` unless you’ve set up bidirectional sync, |
| 94 | rather than have the two backup servers do `pull` only. |
| 95 | |
| 96 | |
| 97 | # Solutions |
| 98 | |
| 99 | The following script solves most of the above problems for the use case |
| 100 | where you want a *nearly-complete* clone of the remote repository using nothing |
| 101 | but the normal Fossil sync protocol. It only does so if you are logged into |
| 102 | the remote as a user with Setup capability, however. |
| @@ -118,11 +118,14 @@ | |
| 118 | out of existence, your backup will be “more than complete” in the sense |
| 119 | that it will continue to have information that the remote says should |
| 120 | not exist any more. That would be not so much a “backup” as an |
| 121 | “archive,” which might not be what you want. |
| 122 | |
| 123 | This method doesn’t get you a copy of the remote’s |
| 124 | [private branches][pbr], on purpose. It may also miss other info on the |
| 125 | remote, such as SQL-level customizations that the sync protocol can’t |
| 126 | see. (Some [ticket system customization][tkt] schemes rely on this ability, for example.) You can |
| 127 | solve such problems if you have access to the remote server, which |
| 128 | allows you to get a SQL-level backup. This requires Fossil 2.12 or |
| @@ -139,12 +142,20 @@ | |
| 139 | bf=repo-$(date +%Y-%m-%d).fossil |
| 140 | ssh example.com "cd museum ; fossil backup -R repo.fossil backups/$bf" && |
| 141 | scp example.com:museum/backups/$bf ~/museum/backups |
| 142 | ``` |
| 143 | |
| 144 | |
| 145 | ## Encrypted Off-Site Backups |
| 146 | |
| 147 | A useful refinement that you can apply to both methods above is |
| 148 | encrypted off-site backups. You may wish to store backups of your |
| 149 | repositories off-site on a service such as Dropbox, Google Drive, iCloud, |
| 150 | or Microsoft OneDrive, where you don’t fully trust the service not to |
| @@ -165,24 +176,10 @@ | |
| 165 | |
| 166 | If you’re adding this to the first script above, remove the |
| 167 | “`-R repo-name`” bit so you get a dump of the repository backing the |
| 168 | current working directory. |
| 169 | |
| 170 | This requires OpenSSL 1.1 or higher. If you’re on 1.0 or older, you |
| 171 | won’t have the `-pbkdf2` and `-iter` options, and you may have to choose |
| 172 | a different cipher algorithm; both changes are likely to weaken the |
| 173 | encryption significantly, so you should install a newer version rather |
| 174 | than work around the lack of these features. |
| 175 | |
| 176 | If you’re on macOS, which |
| 177 | still ships 1.0 as of the time of this writing, [Homebrew][hb] offers |
| 178 | the current version of OpenSSL, but to avoid a conflict with the platform |
| 179 | version it’s [unlinked][hbul] by default, so you have to give an explicit |
| 180 | path to its “cellar” directory: |
| 181 | |
| 182 | /usr/local/Cellar/openssl\@1.1/1.1.1g/bin/openssl ... |
| 183 | |
| 184 | Change the `pass` value to some other long random string, and change the |
| 185 | `iter` value to something between 10000 and 100000. A good source for |
| 186 | the first is [here][grcp], and for the second, [here][rint]. |
| 187 | |
| 188 | Compressing the data before encrypting it removes redundancies that can |
| @@ -192,21 +189,33 @@ | |
| 192 | compression algorithm that takes less CPU power, such as [`lz4`][lz4]. |
| 193 | Changing up the compression algorithm also provides some |
| 194 | security-thru-obscurity, which is useless on its own, but it *is* a |
| 195 | useful adjunct to strong encryption. |
| 196 | |
| 197 | |
| 198 | ## Restoring From An Encrypted Backup |
| 199 | |
| 200 | The “restore” script for the above fragment is basically an inverse of |
| 201 | it, but it’s worth showing it because there are some subtleties to take |
| 202 | care of. If all variables defined in earlier scripts are available, then |
| 203 | restoration is: |
| 204 | |
| 205 | ``` |
| 206 | openssl enc -d -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -in "$gd" | |
| 207 | xz -d | sqlite3 ~/museum/restored-repo.fossil |
| 208 | ``` |
| 209 | |
| 210 | We changed the `-e` to `-d` on the `openssl` command to get decryption, |
| 211 | and we changed the `-out` to `-in` so it reads from the encrypted backup |
| 212 | file and writes the result to stdout. |
| @@ -213,30 +222,29 @@ | |
| 213 | |
| 214 | The decompression step is trivial. |
| 215 | |
| 216 | The last change is tricky: we used `fossil sql` above to ensure that |
| 217 | we’re using the same version of SQLite to write the encrypted backup DB |
| 218 | as was used to maintain the repository, but unfortunately, we can’t get |
| 219 | the built-in SQLite shell to write a backup into an empty database. |
| 220 | (As soon as it starts up, it goes looking for tables created by |
| 221 | `fossil init` and fails with an error.) |
| 222 | Therefore, we have to either run the restoration against a |
| 223 | possibly-different version of SQLite and hope there are no |
| 224 | incompatibilities, or we have to go out of our way to build a matching |
| 225 | version of `sqlite3` before we can safely do the restoration. |
| 226 | |
| 227 | Keep in mind that Fossil often acts as a dogfooding project for SQLite, |
| 228 | making use of the latest features, so it is quite likely that a given |
| 229 | random `sqlite3` binary in your `PATH` will be unable to understand the |
| 230 | file created by “`fossil sql .dump`”! |
| 231 | |
| 232 | [bu]: /help?cmd=backup |
| 233 | [grcp]: https://www.grc.com/passwords.htm |
| 234 | [hb]: https://brew.sh |
| 235 | [hbul]: https://docs.brew.sh/FAQ#what-does-keg-only-mean |
| 236 | [lz4]: https://lz4.github.io/lz4/ |
| 237 | [pbr]: ./private.wiki |
| 238 | [rint]: https://www.random.org/integers/?num=1&min=10000&max=100000&col=5&base=10&format=html&rnd=new |
| 239 | [setup]: ./caps/admin-v-setup.md#apsu |
| 240 | [shun]: ./shunning.wiki |
| 241 | [tkt]: ./tickets.wiki |
| 242 | [uv]: ./unvers.wiki |
| 243 |
| --- www/backup.md | |
| +++ www/backup.md | |
| @@ -1,11 +1,11 @@ | |
| 1 | # Backing Up a Remote Fossil Repository |
| 2 | |
| 3 | One of the great benefits of Fossil and other [distributed version control systems][dvcs] |
| 4 | is that cloning a repository makes a backup. If you are running a project with multiple |
| 5 | developers who share their work using a [central server][server] and the server hardware |
| 6 | catches fire, the clones of the repository on each developer |
| 7 | workstation *may* serve as a suitable backup. |
| 8 | |
| 9 | [dvcs]: wikipedia:/wiki/Distributed_version_control |
| 10 | [server]: ./server/whyuseaserver.wiki |
| 11 | |
| @@ -15,20 +15,20 @@ | |
| 15 | that, a Fossil repository typically contains |
| 16 | other useful information that is not always shared as part of a clone, which might need |
| 17 | to be backed up separately. To wit: |
| 18 | |
| 19 | |
| 20 | ## <a id="pii"></a> Sensitive Information |
| 21 | |
| 22 | Fossil purposefully does not clone certain sensitive information unless |
| 23 | you’re logged in as a user with [Setup] capability. As an example, a local clone |
| 24 | may have a different `user` table than the remote, because only a |
| 25 | Setup user is allowed to see the full version for privacy and security |
| 26 | reasons. |
| 27 | |
| 28 | |
| 29 | ## <a id="config"></a> Configuration Drift |
| 30 | |
| 31 | Fossil allows the local configuration in certain areas to differ from |
| 32 | that of the remote. With the exception of the prior item, you get a copy |
| 33 | of these configuration areas on initial clone, but after that, some |
| 34 | remote configuration changes don’t sync down automatically, such as the |
| @@ -35,37 +35,37 @@ | |
| 35 | remote’s skin. You can ask for updates by running the |
| 36 | [`fossil config pull skin`](./help?cmd=config) command, but that |
| 37 | does not happen automatically during the course of normal development. |
| 38 | |
| 39 | |
| 40 | ## <a id="private"></a> Private Branches |
| 41 | |
| 42 | The very nature of Fossil’s [private branch feature][pbr] ensures that |
| 43 | remote clones don’t get a copy of those branches. Normally this is |
| 44 | exactly what you want, but in the case of making backups, you probably |
| 45 | want to back up these branches as well. One of the two backup methods below |
| 46 | provides this. |
| 47 | |
| 48 | |
| 49 | ## <a id="shun"></a> Shunned Artifacts |
| 50 | |
| 51 | Fossil purposefully doesn’t sync [shunned artifacts][shun]. If you want |
| 52 | your local clone to be a precise match to the remote, it needs to track |
| 53 | changes to the shun table as well. |
| 54 | |
| 55 | |
| 56 | ## <a id="uv"></a> Unversioned Artifacts |
| 57 | |
| 58 | Data in Fossil’s [unversioned artifacts table][uv] doesn’t sync down by |
| 59 | default unless you specifically ask for it. Like local configuration |
| 60 | data, it doesn’t get pulled as part of a normal `fossil sync`, but |
| 61 | *unlike* the config data, you don’t get unversioned files as part of the |
| 62 | initial clone unless you ask for it by passing the `--unversioned/-u` |
| 63 | flag. |
| 64 | |
| 65 | |
| 66 | ## <a id="ait"></a>Autosync Is Intransitive |
| 67 | |
| 68 | If you’re using Fossil in a truly distributed mode, rather than the |
| 69 | simple central-and-clones model that is more common, there may be no |
| 70 | single source of truth in the network because Fossil’s autosync feature |
| 71 | isn’t transitive. |
| @@ -92,11 +92,11 @@ | |
| 92 | source of truth, those users still syncing with `svr2` won’t have their |
| 93 | commits pushed up to `svr1` unless you’ve set up bidirectional sync, |
| 94 | rather than have the two backup servers do `pull` only. |
| 95 | |
| 96 | |
| 97 | # Solution 1: Explicit Pulls |
| 98 | |
| 99 | The following script solves most of the above problems for the use case |
| 100 | where you want a *nearly-complete* clone of the remote repository using nothing |
| 101 | but the normal Fossil sync protocol. It only does so if you are logged into |
| 102 | the remote as a user with Setup capability, however. |
| @@ -118,11 +118,14 @@ | |
| 118 | out of existence, your backup will be “more than complete” in the sense |
| 119 | that it will continue to have information that the remote says should |
| 120 | not exist any more. That would be not so much a “backup” as an |
| 121 | “archive,” which might not be what you want. |
| 122 | |
| 123 | |
| 124 | # Solution 2: SQL-Level Backup |
| 125 | |
| 126 | The first method doesn’t get you a copy of the remote’s |
| 127 | [private branches][pbr], on purpose. It may also miss other info on the |
| 128 | remote, such as SQL-level customizations that the sync protocol can’t |
| 129 | see. (Some [ticket system customization][tkt] schemes rely on this ability, for example.) You can |
| 130 | solve such problems if you have access to the remote server, which |
| 131 | allows you to get a SQL-level backup. This requires Fossil 2.12 or |
| @@ -139,12 +142,20 @@ | |
| 142 | bf=repo-$(date +%Y-%m-%d).fossil |
| 143 | ssh example.com "cd museum ; fossil backup -R repo.fossil backups/$bf" && |
| 144 | scp example.com:museum/backups/$bf ~/museum/backups |
| 145 | ``` |
| 146 | |
| 147 | ---- |
| 148 | |
| 149 | Beware that this method does not solve [the intransitive sync |
| 150 | problem](#ait), in and of itself: if you do a SQL-level backup of a |
| 151 | stale repo DB, you have a *stale backup!* You should therefore run this |
| 152 | on every node that may need to serve as a backup so that at least *one* |
| 153 | of the backups is also up-to-date. |
| 154 | |
| 155 | |
| 156 | # <a id="enc"></a> Encrypted Off-Site Backups |
| 157 | |
| 158 | A useful refinement that you can apply to both methods above is |
| 159 | encrypted off-site backups. You may wish to store backups of your |
| 160 | repositories off-site on a service such as Dropbox, Google Drive, iCloud, |
| 161 | or Microsoft OneDrive, where you don’t fully trust the service not to |
| @@ -165,24 +176,10 @@ | |
| 176 | |
| 177 | If you’re adding this to the first script above, remove the |
| 178 | “`-R repo-name`” bit so you get a dump of the repository backing the |
| 179 | current working directory. |
| 180 | |
| 181 | Change the `pass` value to some other long random string, and change the |
| 182 | `iter` value to something between 10000 and 100000. A good source for |
| 183 | the first is [here][grcp], and for the second, [here][rint]. |
| 184 | |
| 185 | Compressing the data before encrypting it removes redundancies that can |
| @@ -192,21 +189,33 @@ | |
| 189 | compression algorithm that takes less CPU power, such as [`lz4`][lz4]. |
| 190 | Changing up the compression algorithm also provides some |
| 191 | security-thru-obscurity, which is useless on its own, but it *is* a |
| 192 | useful adjunct to strong encryption. |
| 193 | |
| 194 | This requires OpenSSL 1.1 or higher. If you’re on 1.0 or older, you |
| 195 | won’t have the `-pbkdf2` and `-iter` options, and you may have to choose |
| 196 | a different cipher algorithm; both changes are likely to weaken the |
| 197 | encryption significantly, so you should install a newer version rather |
| 198 | than work around the lack of these features. If you’re on macOS, which |
| 199 | still ships 1.0 as of the time of this writing, [Homebrew][hb] offers |
| 200 | the current version of OpenSSL, but to avoid a conflict with the platform |
| 201 | version, it’s [unlinked][hbul] by default, so you have to give an explicit |
| 202 | path to its “cellar” directory: |
| 203 | |
| 204 | /usr/local/Cellar/openssl\@1.1/1.1.1g/bin/openssl ... |
| 205 | |
| 206 | |
| 207 | ## <a id="rest"></a> Restoring From An Encrypted Backup |
| 208 | |
| 209 | The “restore” script for the above fragment is basically an inverse of |
| 210 | it, but it’s worth showing it because there are some subtleties to take |
| 211 | care of. If all variables defined in earlier scripts are available, then |
| 212 | restoration is: |
| 213 | |
| 214 | ``` |
| 215 | openssl enc -d -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -in "$gd" | |
| 216 | xz -d | fossil --no-repository ~/museum/restored-repo.fossil |
| 217 | ``` |
| 218 | |
| 219 | We changed the `-e` to `-d` on the `openssl` command to get decryption, |
| 220 | and we changed the `-out` to `-in` so it reads from the encrypted backup |
| 221 | file and writes the result to stdout. |
| @@ -213,30 +222,29 @@ | |
| 222 | |
| 223 | The decompression step is trivial. |
| 224 | |
| 225 | The last change is tricky: we used `fossil sql` above to ensure that |
| 226 | we’re using the same version of SQLite to write the encrypted backup DB |
| 227 | as was used to maintain the repository. We must also do that on |
| 228 | restoration: |
| 229 | Fossil serves as a dogfooding project for SQLite, |
| 230 | often making use of the latest features, so it is quite likely that a given |
| 231 | random `sqlite3` binary in your `PATH` will be unable to understand the |
| 232 | file created by “`fossil sql .dump`”! The tricky bit is, you can’t just |
| 233 | pipe the decrpted SQL dump into `fossil sql`, because on startup, Fossil |
| 234 | normally goes looking for tables created by `fossil init`, and it won’t |
| 235 | find them in a newly-created repo DB. We get around this by passing |
| 236 | the `--no-repository` flag, which suppresses this behavior. Doing it |
| 237 | this way saves you from needing to go and build a matching version of |
| 238 | `sqlite3` just to restore the backup. |
| 239 | |
| 240 | [bu]: /help?cmd=backup |
| 241 | [grcp]: https://www.grc.com/passwords.htm |
| 242 | [hb]: https://brew.sh |
| 243 | [hbul]: https://docs.brew.sh/FAQ#what-does-keg-only-mean |
| 244 | [lz4]: https://lz4.github.io/lz4/ |
| 245 | [pbr]: ./private.wiki |
| 246 | [rint]: https://www.random.org/integers/?num=1&min=10000&max=100000&col=5&base=10&format=html&rnd=new |
| 247 | [Setup]: ./caps/admin-v-setup.md#apsu |
| 248 | [shun]: ./shunning.wiki |
| 249 | [tkt]: ./tickets.wiki |
| 250 | [uv]: ./unvers.wiki |
| 251 |
+10
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,7 +1,17 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | +<a name='v2_14'></a> | |
| 4 | +<h2>Changes for Version 2.14 (pending)</h2> | |
| 5 | + | |
| 6 | + * The "[/help?cmd=clone|fossil clone]" command is enhanced so that | |
| 7 | + if the repository filename is omitted, an appropriate name is derived | |
| 8 | + from the remote URL and the newly cloned repo is opened. This makes | |
| 9 | + the clone command work more like Git, thus making it easier for | |
| 10 | + people transitioning from Git. | |
| 11 | + * Add the "contact" sub-command to [/help?cmd=user|fossil user]. | |
| 12 | + | |
| 3 | 13 | <a name='v2_13'></a> |
| 4 | 14 | <h2>Changes for Version 2.13 (2020-11-01)</h2> |
| 5 | 15 | |
| 6 | 16 | * Added support for [./interwiki.md|interwiki links]. |
| 7 | 17 | * Enable <del> and <ins> markup in wiki. |
| 8 | 18 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,7 +1,17 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v2_13'></a> |
| 4 | <h2>Changes for Version 2.13 (2020-11-01)</h2> |
| 5 | |
| 6 | * Added support for [./interwiki.md|interwiki links]. |
| 7 | * Enable <del> and <ins> markup in wiki. |
| 8 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,7 +1,17 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v2_14'></a> |
| 4 | <h2>Changes for Version 2.14 (pending)</h2> |
| 5 | |
| 6 | * The "[/help?cmd=clone|fossil clone]" command is enhanced so that |
| 7 | if the repository filename is omitted, an appropriate name is derived |
| 8 | from the remote URL and the newly cloned repo is opened. This makes |
| 9 | the clone command work more like Git, thus making it easier for |
| 10 | people transitioning from Git. |
| 11 | * Add the "contact" sub-command to [/help?cmd=user|fossil user]. |
| 12 | |
| 13 | <a name='v2_13'></a> |
| 14 | <h2>Changes for Version 2.13 (2020-11-01)</h2> |
| 15 | |
| 16 | * Added support for [./interwiki.md|interwiki links]. |
| 17 | * Enable <del> and <ins> markup in wiki. |
| 18 |
+1
-1
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -296,6 +296,6 @@ | ||
| 296 | 296 | # [#tag-ts | TAGNAME:timestamp] |
| 297 | 297 | # Full artifact hash or hash prefix. |
| 298 | 298 | # Any other type of symbolic name that Fossil extracts from |
| 299 | 299 | artifacts. |
| 300 | 300 | |
| 301 | -<div style="height:40em" id="this-space-intentionally-left-blank"></div> | |
| 301 | +<div style="height:50em" id="this-space-intentionally-left-blank"></div> | |
| 302 | 302 | |
| 303 | 303 | ADDED www/ckout-workflows.md |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -296,6 +296,6 @@ | |
| 296 | # [#tag-ts | TAGNAME:timestamp] |
| 297 | # Full artifact hash or hash prefix. |
| 298 | # Any other type of symbolic name that Fossil extracts from |
| 299 | artifacts. |
| 300 | |
| 301 | <div style="height:40em" id="this-space-intentionally-left-blank"></div> |
| 302 | |
| 303 | DDED www/ckout-workflows.md |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -296,6 +296,6 @@ | |
| 296 | # [#tag-ts | TAGNAME:timestamp] |
| 297 | # Full artifact hash or hash prefix. |
| 298 | # Any other type of symbolic name that Fossil extracts from |
| 299 | artifacts. |
| 300 | |
| 301 | <div style="height:50em" id="this-space-intentionally-left-blank"></div> |
| 302 | |
| 303 | DDED www/ckout-workflows.md |
+33
| --- a/www/ckout-workflows.md | ||
| +++ b/www/ckout-workflows.md | ||
| @@ -0,0 +1,33 @@ | ||
| 1 | +# Check-Out WorWith Fossil 2.14 �# Check-Out Workflows | |
| 2 | + | |
| 3 | +Be # Check-Out Workflows | |
| 4 | + | |
| 5 | +Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d , leaving its `git-workWith Git’s typicalFossil working model, | |
| 6 | +With the clone done as in [the prior section](#mdw), the most idiomatic | |
| 7 | +The Clone-and-Open Wayhat allows you to get clbehavior: | |
| 8 | +The use of [`fossil openclone`][clone] | |
| 9 | +is likely to surprise a Git user. When we were [discussing][caod] | |
| 10 | +this, we considered following the Git command style, but we decided | |
| 11 | +against it because it goes against this core Fossil design principle: | |
| 12 | +given that the Fossil repo is separate from the check-out, why would you | |
| 13 | +expect asking for a repo clone to also create a check-out directory for | |
| 14 | +you? We view commingled repository + check-out as a design error in | |
| 15 | +Git, so why would we repeat the error? | |
| 16 | + | |
| 17 | +To see why we see this behavior is error-prone, consider that | |
| 18 | +`git clean` must have an exception to avoid nuking the `.git` directory. | |
| 19 | +We had to add that complication to `fossil clean` when we added the | |
| 20 | +`fossil open URI` feature: it won’t nuke the repo DB file. | |
| 21 | + | |
| 22 | +[clone]: /help?cmd=clone | |
| 23 | +[open]: /help?cmd=openThe Git Clone Way | |
| 24 | + | |
| 25 | +This feature didn’t placate many Git fans, though, so w# Check-Out WorWithi# Check-Out WorWith Fossil 2# Check-Out Wokflows | |
| 26 | + | |
| 27 | +Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d # Check-Out WorWik-Out Workflows | |
| 28 | + | |
| 29 | +Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d # Check-Out WorWith Fossil 2.14 �# Check-Out Workflows | |
| 30 | + | |
| 31 | +Be # Check-Out Workflows | |
| 32 | + | |
| 33 | +Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d rum/forumpost/3f143cec74 |
| --- a/www/ckout-workflows.md | |
| +++ b/www/ckout-workflows.md | |
| @@ -0,0 +1,33 @@ | |
| --- a/www/ckout-workflows.md | |
| +++ b/www/ckout-workflows.md | |
| @@ -0,0 +1,33 @@ | |
| 1 | # Check-Out WorWith Fossil 2.14 �# Check-Out Workflows |
| 2 | |
| 3 | Be # Check-Out Workflows |
| 4 | |
| 5 | Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d , leaving its `git-workWith Git’s typicalFossil working model, |
| 6 | With the clone done as in [the prior section](#mdw), the most idiomatic |
| 7 | The Clone-and-Open Wayhat allows you to get clbehavior: |
| 8 | The use of [`fossil openclone`][clone] |
| 9 | is likely to surprise a Git user. When we were [discussing][caod] |
| 10 | this, we considered following the Git command style, but we decided |
| 11 | against it because it goes against this core Fossil design principle: |
| 12 | given that the Fossil repo is separate from the check-out, why would you |
| 13 | expect asking for a repo clone to also create a check-out directory for |
| 14 | you? We view commingled repository + check-out as a design error in |
| 15 | Git, so why would we repeat the error? |
| 16 | |
| 17 | To see why we see this behavior is error-prone, consider that |
| 18 | `git clean` must have an exception to avoid nuking the `.git` directory. |
| 19 | We had to add that complication to `fossil clean` when we added the |
| 20 | `fossil open URI` feature: it won’t nuke the repo DB file. |
| 21 | |
| 22 | [clone]: /help?cmd=clone |
| 23 | [open]: /help?cmd=openThe Git Clone Way |
| 24 | |
| 25 | This feature didn’t placate many Git fans, though, so w# Check-Out WorWithi# Check-Out WorWith Fossil 2# Check-Out Wokflows |
| 26 | |
| 27 | Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d # Check-Out WorWik-Out Workflows |
| 28 | |
| 29 | Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d # Check-Out WorWith Fossil 2.14 �# Check-Out Workflows |
| 30 | |
| 31 | Be # Check-Out Workflows |
| 32 | |
| 33 | Because Fossil separates the concept of “check-out d e Fossil separates the concept of “check-out d rum/forumpost/3f143cec74 |
+88
-35
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -25,10 +25,13 @@ | ||
| 25 | 25 | we try to be fair, the information here |
| 26 | 26 | might be biased in favor of Fossil, if only because we spend most of our |
| 27 | 27 | time using Fossil, not Git. Ask around for second opinions from |
| 28 | 28 | people who have used <em>both</em> Fossil and Git. |
| 29 | 29 | |
| 30 | +If you want a more practical, less philosophical guide to moving from | |
| 31 | +Git to Fossil, see our [./gitusers.md | Git to Fossil Translation Guide]. | |
| 32 | + | |
| 30 | 33 | |
| 31 | 34 | <h2>2.0 Differences Between Fossil And Git</h2> |
| 32 | 35 | |
| 33 | 36 | Differences between Fossil and Git are summarized by the following table, |
| 34 | 37 | with further description in the text that follows. |
| @@ -645,21 +648,20 @@ | ||
| 645 | 648 | standard advice is to use a switch-in-place workflow in Fossil when |
| 646 | 649 | the disturbance from switching branches is small, and to use multiple |
| 647 | 650 | checkouts when you have long-lived working branches that are different |
| 648 | 651 | enough that switching in place is disruptive. |
| 649 | 652 | |
| 650 | -You can use Git in the Fossil style, either by manually symlinking the | |
| 651 | -<tt>.git</tt> directory from one working directory to another or by use | |
| 652 | -of the <tt>[https://git-scm.com/docs/git-worktree|git-worktree]</tt> | |
| 653 | -feature. Nevertheless, Git's default tie between working directory and | |
| 653 | +While you can [./gitusers.md#worktree | use Git in the Fossil style], | |
| 654 | +Git's default tie between working directory and | |
| 654 | 655 | repository means the standard method for working with a Git repo is to |
| 655 | 656 | have one working directory only. Most Git tutorials teach this style, so |
| 656 | 657 | it is how most people learn to use Git. Because relatively few people |
| 657 | 658 | use Git with multiple working directories per repository, there are |
| 658 | 659 | [https://duckduckgo.com/?q=git+worktree+problem | several known |
| 659 | 660 | problems] with that way of working, problems which don't happen in Fossil because of |
| 660 | -the clear separation between repository and working directory. | |
| 661 | +the clear [./ckout-workflows.md | separation] between a Fossil repository and | |
| 662 | +each working directory. | |
| 661 | 663 | |
| 662 | 664 | This distinction matters because switching branches inside a single working directory loses local context |
| 663 | 665 | on each switch. |
| 664 | 666 | |
| 665 | 667 | For instance, in any software project where the runnable program must be |
| @@ -695,13 +697,16 @@ | ||
| 695 | 697 | |
| 696 | 698 | <h3 id="history">2.7 What you should have done vs. What you actually did</h3> |
| 697 | 699 | |
| 698 | 700 | Git puts a lot of emphasis on maintaining |
| 699 | 701 | a "clean" check-in history. Extraneous and experimental branches by |
| 700 | -individual developers often never make it into the main repository. And | |
| 701 | -branches are often rebased before being pushed, to make | |
| 702 | -it appear as if development had been linear. Git strives to record what | |
| 702 | +individual developers often never make it into the main repository. | |
| 703 | +Branches may be rebased before being pushed to make | |
| 704 | +it appear as if development had been linear, or "squashed" to make it | |
| 705 | +appear that multiple commits were made as a single commit. | |
| 706 | +There are [https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History | | |
| 707 | +other history rewriting mechanisms in Git] as well. Git strives to record what | |
| 703 | 708 | the development of a project should have looked like had there been no |
| 704 | 709 | mistakes. |
| 705 | 710 | |
| 706 | 711 | Fossil, in contrast, puts more emphasis on recording exactly what happened, |
| 707 | 712 | including all of the messy errors, dead-ends, experimental branches, and |
| @@ -714,69 +719,117 @@ | ||
| 714 | 719 | Like Git, Fossil has an [/help?cmd=amend|amend command] for modifying |
| 715 | 720 | prior commits, but unlike in Git, this works not by replacing data in |
| 716 | 721 | the repository, but by adding a correction record to the repository that |
| 717 | 722 | affects how later Fossil operations present the corrected data. The old |
| 718 | 723 | information is still there in the repository, it is just overridden from |
| 719 | -the amendment point forward. For extreme situations, Fossil adds the | |
| 720 | -[/doc/trunk/www/shunning.wiki|shunning mechanism], but it has strict | |
| 721 | -limitations that prevent global history rewrites. | |
| 724 | +the amendment point forward. | |
| 725 | + | |
| 726 | +Fossil lacks almost every other history rewriting mechanism listed on | |
| 727 | +the Git documentation page linked above. [./rebaseharm.md | There is no | |
| 728 | +rebase] in Fossil, on purpose, thus no way to reorder or copy commits | |
| 729 | +around in the commit hash tree. There is no commit squashing, dropping, | |
| 730 | +or interactive patch-based cherry-picking of commit elements in Fossil. | |
| 731 | +There is nothing like Git's <tt>filter-branch</tt> in Fossil. | |
| 732 | + | |
| 733 | +The lone exception is deleting commits. Fossil has two methods for doing | |
| 734 | +that, both of which have stringent limitations, on purpose. | |
| 735 | + | |
| 736 | +The first is [/doc/trunk/www/shunning.wiki | shunning]. See that | |
| 737 | +document for details, but briefly, you only get mandatory compliance | |
| 738 | +for shun requests within a single repository. Shun requests do not | |
| 739 | +propagate automatically between repository clones. A Fossil repository | |
| 740 | +administrator can <i>cooperatively</i> pull another repo's shun requests | |
| 741 | +across a sync boundary, so that two admins can get together and agree to | |
| 742 | +shun certain committed artifacts, but a person cannot force their local | |
| 743 | +shun requests into another repo without having admin-level control over | |
| 744 | +the receiving repo as well. Fossil's shun feature isn't for fixing up | |
| 745 | +everyday bad commits, it's for dealing with extreme situations: public | |
| 746 | +commits of secret material, ticket/wiki/forum spam, law enforcement | |
| 747 | +takedown demands, etc. | |
| 748 | + | |
| 749 | +There is also the experimental [/help?cmd=purge | <tt>purge</tt> | |
| 750 | +command], which differs from shunning in ways that aren't especially | |
| 751 | +important in the context of this document. At a 30000 foot level, you | |
| 752 | +can think of purging as useful only when you've turned off Fossil's | |
| 753 | +autosync feature and want to pluck artifacts out of its hash tree before | |
| 754 | +they get pushed. In that sense, it's approximately the same as | |
| 755 | +<tt>git rebase -i, drop</tt>. However, given that Fossil defaults to | |
| 756 | +having autosync enabled [#devorg | for good reason], the purge command | |
| 757 | +isn't very useful in practice: once a commit has been pushed into | |
| 758 | +another repo, shunning is more useful if you need to delete it from | |
| 759 | +history. | |
| 760 | + | |
| 761 | +If these accommodations strike you as incoherent with respect to | |
| 762 | +Fossil's philosophy of durable, unchanging commits, realize that if | |
| 763 | +shunning and purging were removed from Fossil, you could still remove | |
| 764 | +artifacts from the repository with SQL <tt>DELETE</tt> statements; the | |
| 765 | +repository database file is, after all, directly modifiable, being | |
| 766 | +writable by your user. Where the Fossil philosophy really takes hold is | |
| 767 | +in making it difficult to violate the integrity of the hash tree. | |
| 768 | +It's somewhat tangential, but the document [./blockchain.md | "Is Fossil | |
| 769 | +a Blockchain?"] touches on this and related topics. | |
| 722 | 770 | |
| 723 | 771 | One commentator characterized Git as recording history according to |
| 724 | 772 | the victors, whereas Fossil records history as it actually happened. |
| 725 | 773 | |
| 726 | -We go into more detail on this topic in a separate article, | |
| 727 | -[./rebaseharm.md | Rebase Considered Harmful]. | |
| 728 | - | |
| 729 | 774 | |
| 730 | 775 | <h3 id="testing">2.8 Test Before Commit</h3> |
| 731 | 776 | |
| 732 | 777 | One of the things that falls out of Git's default separation of commit |
| 733 | 778 | from push is that there are several Git sub-commands that jump straight |
| 734 | 779 | to the commit step before a change could possibly be tested. Fossil, by |
| 735 | 780 | contrast, makes the equivalent change to the local working check-out |
| 736 | 781 | only, requiring a separate check-in step to commit the change. This |
| 737 | 782 | design difference falls naturally out of Fossil's default-enabled |
| 738 | -autosync feature. | |
| 783 | +autosync feature and its philosophy of [#history | not offering history | |
| 784 | +rewriting features]. | |
| 739 | 785 | |
| 740 | 786 | The prime example in Git is rebasing: the change happens to the local |
| 741 | 787 | repository immediately if successful, even though you haven't tested the |
| 742 | 788 | change yet. It's possible to argue for such a design in a tool like Git |
| 743 | -which doesn't automatically push the change up to its parent, because | |
| 744 | -you can still test the change before pushing local changes to the parent | |
| 745 | -repo, but in the meantime you've made a durable change to your local Git | |
| 746 | -repository. You must do something drastic like <tt>git | |
| 747 | -reset --hard</tt> to revert that rebase if it causes a problem. If you | |
| 748 | -push your rebased local repo up to the parent without testing first, | |
| 749 | -you've now committed the error on a public branch, effectively a | |
| 750 | -violation of | |
| 789 | +since it lacks an autosync feature, because you can still test the | |
| 790 | +change before pushing local changes to the parent repo, but in the | |
| 791 | +meantime you've made a durable change to your local Git repository. You | |
| 792 | +must do something drastic like <tt>git reset --hard</tt> to revert that | |
| 793 | +rebase or rewrite history before pushing it if the rebase causes a | |
| 794 | +problem. If you push your rebased local repo up to the parent without | |
| 795 | +testing first, you cannot fix it without violating | |
| 751 | 796 | [https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing |
| 752 | 797 | | the golden rule of rebasing]. |
| 753 | 798 | |
| 754 | 799 | Lesser examples are the Git <tt>merge</tt>, <tt>cherry-pick</tt>, and |
| 755 | 800 | <tt>revert</tt> commands, all of which apply work from one branch onto |
| 756 | -another, and all of which do their work immediately without giving you | |
| 757 | -an opportunity to test the change first locally unless you give the | |
| 758 | -<tt>--no-commit</tt> option. | |
| 801 | +another, and all of which commit their change to the local repository | |
| 802 | +immediately without giving you | |
| 803 | +an opportunity to test the change first unless you give the | |
| 804 | +<tt>--no-commit</tt> option. Otherwise, you're back in the same boat: | |
| 805 | +reset the local repository or rewrite history to fix things, then maybe | |
| 806 | +retry. | |
| 759 | 807 | |
| 760 | 808 | Fossil cannot sensibly work that way because of its default-enabled |
| 761 | -autosync feature. Instead of jumping straight to the commit step, Fossil | |
| 809 | +autosync feature and its purposeful paucity of commands for modifying | |
| 810 | +commits, as discussed in [#history | the prior section]. | |
| 811 | + | |
| 812 | +Instead of jumping straight to the commit step, Fossil | |
| 762 | 813 | applies the proposed merge to the local working directory only, |
| 763 | 814 | requiring a separate check-in step before the change is committed to the |
| 764 | 815 | repository. This gives you a chance to test the change first, |
| 765 | 816 | either manually or by running your software's automatic tests. (Ideally, |
| 766 | -both!) | |
| 817 | +both!) Thus, Fossil doesn't need rebase, squashing, | |
| 818 | +<tt>reset --hard</tt>, or other Git commit mutating mechanisms. | |
| 767 | 819 | |
| 768 | -Another difference is that because Fossil requires an explicit commit | |
| 769 | -for a merge, it makes you give an explicit commit <i>message</i> for | |
| 770 | -each merge, whereas Git writes that commit message itself by default | |
| 820 | +Because Fossil requires an explicit commit for a merge, it has the nice | |
| 821 | +side benefit that it makes you give an explicit commit <i>message</i> | |
| 822 | +for each merge, whereas Git writes that commit message itself by default | |
| 771 | 823 | unless you give the optional <tt>--edit</tt> flag to override it. |
| 772 | 824 | |
| 773 | 825 | We don't look at this difference as a workaround in Fossil for autosync, |
| 774 | -but instead as a test-first philosophical difference. When every commit | |
| 775 | -is pushed to the parent repo by default, it encourages a working style | |
| 776 | -in which every commit is tested first. We think this is an inherently | |
| 777 | -good thing. | |
| 826 | +but instead as a test-first philosophical difference: | |
| 827 | +<tt>fossil commit</tt> is a <i>commitment</i>. When every commit is | |
| 828 | +pushed to the parent repo by default, it encourages a working style in | |
| 829 | +which every commit is tested first. It encourages thinking before | |
| 830 | +acting. We believe this is an inherently good thing. | |
| 778 | 831 | |
| 779 | 832 | Incidentally, this is a good example of Git's messy command design. |
| 780 | 833 | These three commands: |
| 781 | 834 | |
| 782 | 835 | <pre> |
| 783 | 836 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -25,10 +25,13 @@ | |
| 25 | we try to be fair, the information here |
| 26 | might be biased in favor of Fossil, if only because we spend most of our |
| 27 | time using Fossil, not Git. Ask around for second opinions from |
| 28 | people who have used <em>both</em> Fossil and Git. |
| 29 | |
| 30 | |
| 31 | <h2>2.0 Differences Between Fossil And Git</h2> |
| 32 | |
| 33 | Differences between Fossil and Git are summarized by the following table, |
| 34 | with further description in the text that follows. |
| @@ -645,21 +648,20 @@ | |
| 645 | standard advice is to use a switch-in-place workflow in Fossil when |
| 646 | the disturbance from switching branches is small, and to use multiple |
| 647 | checkouts when you have long-lived working branches that are different |
| 648 | enough that switching in place is disruptive. |
| 649 | |
| 650 | You can use Git in the Fossil style, either by manually symlinking the |
| 651 | <tt>.git</tt> directory from one working directory to another or by use |
| 652 | of the <tt>[https://git-scm.com/docs/git-worktree|git-worktree]</tt> |
| 653 | feature. Nevertheless, Git's default tie between working directory and |
| 654 | repository means the standard method for working with a Git repo is to |
| 655 | have one working directory only. Most Git tutorials teach this style, so |
| 656 | it is how most people learn to use Git. Because relatively few people |
| 657 | use Git with multiple working directories per repository, there are |
| 658 | [https://duckduckgo.com/?q=git+worktree+problem | several known |
| 659 | problems] with that way of working, problems which don't happen in Fossil because of |
| 660 | the clear separation between repository and working directory. |
| 661 | |
| 662 | This distinction matters because switching branches inside a single working directory loses local context |
| 663 | on each switch. |
| 664 | |
| 665 | For instance, in any software project where the runnable program must be |
| @@ -695,13 +697,16 @@ | |
| 695 | |
| 696 | <h3 id="history">2.7 What you should have done vs. What you actually did</h3> |
| 697 | |
| 698 | Git puts a lot of emphasis on maintaining |
| 699 | a "clean" check-in history. Extraneous and experimental branches by |
| 700 | individual developers often never make it into the main repository. And |
| 701 | branches are often rebased before being pushed, to make |
| 702 | it appear as if development had been linear. Git strives to record what |
| 703 | the development of a project should have looked like had there been no |
| 704 | mistakes. |
| 705 | |
| 706 | Fossil, in contrast, puts more emphasis on recording exactly what happened, |
| 707 | including all of the messy errors, dead-ends, experimental branches, and |
| @@ -714,69 +719,117 @@ | |
| 714 | Like Git, Fossil has an [/help?cmd=amend|amend command] for modifying |
| 715 | prior commits, but unlike in Git, this works not by replacing data in |
| 716 | the repository, but by adding a correction record to the repository that |
| 717 | affects how later Fossil operations present the corrected data. The old |
| 718 | information is still there in the repository, it is just overridden from |
| 719 | the amendment point forward. For extreme situations, Fossil adds the |
| 720 | [/doc/trunk/www/shunning.wiki|shunning mechanism], but it has strict |
| 721 | limitations that prevent global history rewrites. |
| 722 | |
| 723 | One commentator characterized Git as recording history according to |
| 724 | the victors, whereas Fossil records history as it actually happened. |
| 725 | |
| 726 | We go into more detail on this topic in a separate article, |
| 727 | [./rebaseharm.md | Rebase Considered Harmful]. |
| 728 | |
| 729 | |
| 730 | <h3 id="testing">2.8 Test Before Commit</h3> |
| 731 | |
| 732 | One of the things that falls out of Git's default separation of commit |
| 733 | from push is that there are several Git sub-commands that jump straight |
| 734 | to the commit step before a change could possibly be tested. Fossil, by |
| 735 | contrast, makes the equivalent change to the local working check-out |
| 736 | only, requiring a separate check-in step to commit the change. This |
| 737 | design difference falls naturally out of Fossil's default-enabled |
| 738 | autosync feature. |
| 739 | |
| 740 | The prime example in Git is rebasing: the change happens to the local |
| 741 | repository immediately if successful, even though you haven't tested the |
| 742 | change yet. It's possible to argue for such a design in a tool like Git |
| 743 | which doesn't automatically push the change up to its parent, because |
| 744 | you can still test the change before pushing local changes to the parent |
| 745 | repo, but in the meantime you've made a durable change to your local Git |
| 746 | repository. You must do something drastic like <tt>git |
| 747 | reset --hard</tt> to revert that rebase if it causes a problem. If you |
| 748 | push your rebased local repo up to the parent without testing first, |
| 749 | you've now committed the error on a public branch, effectively a |
| 750 | violation of |
| 751 | [https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing |
| 752 | | the golden rule of rebasing]. |
| 753 | |
| 754 | Lesser examples are the Git <tt>merge</tt>, <tt>cherry-pick</tt>, and |
| 755 | <tt>revert</tt> commands, all of which apply work from one branch onto |
| 756 | another, and all of which do their work immediately without giving you |
| 757 | an opportunity to test the change first locally unless you give the |
| 758 | <tt>--no-commit</tt> option. |
| 759 | |
| 760 | Fossil cannot sensibly work that way because of its default-enabled |
| 761 | autosync feature. Instead of jumping straight to the commit step, Fossil |
| 762 | applies the proposed merge to the local working directory only, |
| 763 | requiring a separate check-in step before the change is committed to the |
| 764 | repository. This gives you a chance to test the change first, |
| 765 | either manually or by running your software's automatic tests. (Ideally, |
| 766 | both!) |
| 767 | |
| 768 | Another difference is that because Fossil requires an explicit commit |
| 769 | for a merge, it makes you give an explicit commit <i>message</i> for |
| 770 | each merge, whereas Git writes that commit message itself by default |
| 771 | unless you give the optional <tt>--edit</tt> flag to override it. |
| 772 | |
| 773 | We don't look at this difference as a workaround in Fossil for autosync, |
| 774 | but instead as a test-first philosophical difference. When every commit |
| 775 | is pushed to the parent repo by default, it encourages a working style |
| 776 | in which every commit is tested first. We think this is an inherently |
| 777 | good thing. |
| 778 | |
| 779 | Incidentally, this is a good example of Git's messy command design. |
| 780 | These three commands: |
| 781 | |
| 782 | <pre> |
| 783 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -25,10 +25,13 @@ | |
| 25 | we try to be fair, the information here |
| 26 | might be biased in favor of Fossil, if only because we spend most of our |
| 27 | time using Fossil, not Git. Ask around for second opinions from |
| 28 | people who have used <em>both</em> Fossil and Git. |
| 29 | |
| 30 | If you want a more practical, less philosophical guide to moving from |
| 31 | Git to Fossil, see our [./gitusers.md | Git to Fossil Translation Guide]. |
| 32 | |
| 33 | |
| 34 | <h2>2.0 Differences Between Fossil And Git</h2> |
| 35 | |
| 36 | Differences between Fossil and Git are summarized by the following table, |
| 37 | with further description in the text that follows. |
| @@ -645,21 +648,20 @@ | |
| 648 | standard advice is to use a switch-in-place workflow in Fossil when |
| 649 | the disturbance from switching branches is small, and to use multiple |
| 650 | checkouts when you have long-lived working branches that are different |
| 651 | enough that switching in place is disruptive. |
| 652 | |
| 653 | While you can [./gitusers.md#worktree | use Git in the Fossil style], |
| 654 | Git's default tie between working directory and |
| 655 | repository means the standard method for working with a Git repo is to |
| 656 | have one working directory only. Most Git tutorials teach this style, so |
| 657 | it is how most people learn to use Git. Because relatively few people |
| 658 | use Git with multiple working directories per repository, there are |
| 659 | [https://duckduckgo.com/?q=git+worktree+problem | several known |
| 660 | problems] with that way of working, problems which don't happen in Fossil because of |
| 661 | the clear [./ckout-workflows.md | separation] between a Fossil repository and |
| 662 | each working directory. |
| 663 | |
| 664 | This distinction matters because switching branches inside a single working directory loses local context |
| 665 | on each switch. |
| 666 | |
| 667 | For instance, in any software project where the runnable program must be |
| @@ -695,13 +697,16 @@ | |
| 697 | |
| 698 | <h3 id="history">2.7 What you should have done vs. What you actually did</h3> |
| 699 | |
| 700 | Git puts a lot of emphasis on maintaining |
| 701 | a "clean" check-in history. Extraneous and experimental branches by |
| 702 | individual developers often never make it into the main repository. |
| 703 | Branches may be rebased before being pushed to make |
| 704 | it appear as if development had been linear, or "squashed" to make it |
| 705 | appear that multiple commits were made as a single commit. |
| 706 | There are [https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History | |
| 707 | other history rewriting mechanisms in Git] as well. Git strives to record what |
| 708 | the development of a project should have looked like had there been no |
| 709 | mistakes. |
| 710 | |
| 711 | Fossil, in contrast, puts more emphasis on recording exactly what happened, |
| 712 | including all of the messy errors, dead-ends, experimental branches, and |
| @@ -714,69 +719,117 @@ | |
| 719 | Like Git, Fossil has an [/help?cmd=amend|amend command] for modifying |
| 720 | prior commits, but unlike in Git, this works not by replacing data in |
| 721 | the repository, but by adding a correction record to the repository that |
| 722 | affects how later Fossil operations present the corrected data. The old |
| 723 | information is still there in the repository, it is just overridden from |
| 724 | the amendment point forward. |
| 725 | |
| 726 | Fossil lacks almost every other history rewriting mechanism listed on |
| 727 | the Git documentation page linked above. [./rebaseharm.md | There is no |
| 728 | rebase] in Fossil, on purpose, thus no way to reorder or copy commits |
| 729 | around in the commit hash tree. There is no commit squashing, dropping, |
| 730 | or interactive patch-based cherry-picking of commit elements in Fossil. |
| 731 | There is nothing like Git's <tt>filter-branch</tt> in Fossil. |
| 732 | |
| 733 | The lone exception is deleting commits. Fossil has two methods for doing |
| 734 | that, both of which have stringent limitations, on purpose. |
| 735 | |
| 736 | The first is [/doc/trunk/www/shunning.wiki | shunning]. See that |
| 737 | document for details, but briefly, you only get mandatory compliance |
| 738 | for shun requests within a single repository. Shun requests do not |
| 739 | propagate automatically between repository clones. A Fossil repository |
| 740 | administrator can <i>cooperatively</i> pull another repo's shun requests |
| 741 | across a sync boundary, so that two admins can get together and agree to |
| 742 | shun certain committed artifacts, but a person cannot force their local |
| 743 | shun requests into another repo without having admin-level control over |
| 744 | the receiving repo as well. Fossil's shun feature isn't for fixing up |
| 745 | everyday bad commits, it's for dealing with extreme situations: public |
| 746 | commits of secret material, ticket/wiki/forum spam, law enforcement |
| 747 | takedown demands, etc. |
| 748 | |
| 749 | There is also the experimental [/help?cmd=purge | <tt>purge</tt> |
| 750 | command], which differs from shunning in ways that aren't especially |
| 751 | important in the context of this document. At a 30000 foot level, you |
| 752 | can think of purging as useful only when you've turned off Fossil's |
| 753 | autosync feature and want to pluck artifacts out of its hash tree before |
| 754 | they get pushed. In that sense, it's approximately the same as |
| 755 | <tt>git rebase -i, drop</tt>. However, given that Fossil defaults to |
| 756 | having autosync enabled [#devorg | for good reason], the purge command |
| 757 | isn't very useful in practice: once a commit has been pushed into |
| 758 | another repo, shunning is more useful if you need to delete it from |
| 759 | history. |
| 760 | |
| 761 | If these accommodations strike you as incoherent with respect to |
| 762 | Fossil's philosophy of durable, unchanging commits, realize that if |
| 763 | shunning and purging were removed from Fossil, you could still remove |
| 764 | artifacts from the repository with SQL <tt>DELETE</tt> statements; the |
| 765 | repository database file is, after all, directly modifiable, being |
| 766 | writable by your user. Where the Fossil philosophy really takes hold is |
| 767 | in making it difficult to violate the integrity of the hash tree. |
| 768 | It's somewhat tangential, but the document [./blockchain.md | "Is Fossil |
| 769 | a Blockchain?"] touches on this and related topics. |
| 770 | |
| 771 | One commentator characterized Git as recording history according to |
| 772 | the victors, whereas Fossil records history as it actually happened. |
| 773 | |
| 774 | |
| 775 | <h3 id="testing">2.8 Test Before Commit</h3> |
| 776 | |
| 777 | One of the things that falls out of Git's default separation of commit |
| 778 | from push is that there are several Git sub-commands that jump straight |
| 779 | to the commit step before a change could possibly be tested. Fossil, by |
| 780 | contrast, makes the equivalent change to the local working check-out |
| 781 | only, requiring a separate check-in step to commit the change. This |
| 782 | design difference falls naturally out of Fossil's default-enabled |
| 783 | autosync feature and its philosophy of [#history | not offering history |
| 784 | rewriting features]. |
| 785 | |
| 786 | The prime example in Git is rebasing: the change happens to the local |
| 787 | repository immediately if successful, even though you haven't tested the |
| 788 | change yet. It's possible to argue for such a design in a tool like Git |
| 789 | since it lacks an autosync feature, because you can still test the |
| 790 | change before pushing local changes to the parent repo, but in the |
| 791 | meantime you've made a durable change to your local Git repository. You |
| 792 | must do something drastic like <tt>git reset --hard</tt> to revert that |
| 793 | rebase or rewrite history before pushing it if the rebase causes a |
| 794 | problem. If you push your rebased local repo up to the parent without |
| 795 | testing first, you cannot fix it without violating |
| 796 | [https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing |
| 797 | | the golden rule of rebasing]. |
| 798 | |
| 799 | Lesser examples are the Git <tt>merge</tt>, <tt>cherry-pick</tt>, and |
| 800 | <tt>revert</tt> commands, all of which apply work from one branch onto |
| 801 | another, and all of which commit their change to the local repository |
| 802 | immediately without giving you |
| 803 | an opportunity to test the change first unless you give the |
| 804 | <tt>--no-commit</tt> option. Otherwise, you're back in the same boat: |
| 805 | reset the local repository or rewrite history to fix things, then maybe |
| 806 | retry. |
| 807 | |
| 808 | Fossil cannot sensibly work that way because of its default-enabled |
| 809 | autosync feature and its purposeful paucity of commands for modifying |
| 810 | commits, as discussed in [#history | the prior section]. |
| 811 | |
| 812 | Instead of jumping straight to the commit step, Fossil |
| 813 | applies the proposed merge to the local working directory only, |
| 814 | requiring a separate check-in step before the change is committed to the |
| 815 | repository. This gives you a chance to test the change first, |
| 816 | either manually or by running your software's automatic tests. (Ideally, |
| 817 | both!) Thus, Fossil doesn't need rebase, squashing, |
| 818 | <tt>reset --hard</tt>, or other Git commit mutating mechanisms. |
| 819 | |
| 820 | Because Fossil requires an explicit commit for a merge, it has the nice |
| 821 | side benefit that it makes you give an explicit commit <i>message</i> |
| 822 | for each merge, whereas Git writes that commit message itself by default |
| 823 | unless you give the optional <tt>--edit</tt> flag to override it. |
| 824 | |
| 825 | We don't look at this difference as a workaround in Fossil for autosync, |
| 826 | but instead as a test-first philosophical difference: |
| 827 | <tt>fossil commit</tt> is a <i>commitment</i>. When every commit is |
| 828 | pushed to the parent repo by default, it encourages a working style in |
| 829 | which every commit is tested first. It encourages thinking before |
| 830 | acting. We believe this is an inherently good thing. |
| 831 | |
| 832 | Incidentally, this is a good example of Git's messy command design. |
| 833 | These three commands: |
| 834 | |
| 835 | <pre> |
| 836 |
+705
-202
| --- www/gitusers.md | ||
| +++ www/gitusers.md | ||
| @@ -1,187 +1,462 @@ | ||
| 1 | -# Hints For Users With Prior Git Experience | |
| 2 | - | |
| 3 | -This document is a semi-random collection of hints intended to help | |
| 4 | -new users of Fossil who have had prior exposure to Git. In other words, | |
| 5 | -this document tries to describe the differences in how Fossil works | |
| 6 | -from the perspective of Git users. | |
| 7 | - | |
| 8 | - | |
| 9 | -## Help Improve This Document | |
| 10 | - | |
| 11 | -If you have a lot of prior Git experience, and you are new to Fossil | |
| 12 | -and are struggling with some concepts, please ask for help on the | |
| 13 | -[Fossil Forum][1]. The people who write this document are intimately | |
| 14 | -familiar with Fossil and less familiar with Git. It is difficult for | |
| 15 | -us to anticipate the perspective of people who are initimately familiar | |
| 16 | -with Git and less familiar with Fossil. Asking questions on the Forum | |
| 17 | -will help us to improve the document. | |
| 18 | - | |
| 19 | -[1]: https://fossil-scm.org/forum | |
| 20 | - | |
| 21 | -Specific suggestions on how to improve this document are also welcomed, | |
| 22 | -of course. | |
| 23 | - | |
| 24 | - | |
| 25 | - | |
| 26 | -## <a id="term"></a> Terminology | |
| 1 | +# Git to Fossil Translation Guide | |
| 2 | + | |
| 3 | +## Introduction | |
| 4 | + | |
| 5 | +This document attempts to provide equivalents for common Git commands | |
| 6 | +and workflows where possible, and where not, to explain those cases. | |
| 7 | + | |
| 8 | +Although Fossil shares many similarities with Git, there are enough | |
| 9 | +differences that we can’t provide a simple “translation dictionary” for | |
| 10 | +some commands. This document is more concerned with those cases than the | |
| 11 | +simple 1:1 mappings, which you can likely find on your own. In many | |
| 12 | +cases, the sub-commands are identical: [`fossil bisect`][bis] does essentially | |
| 13 | +the same thing as `git bisect`, for example. | |
| 14 | + | |
| 15 | +We present this from the perspective of Git users moving to Fossil, but | |
| 16 | +it is also possible to read this document as a Fossil user who speaks | |
| 17 | +only pidgin Git, who may often have questions of the form, “Now how do I | |
| 18 | +do X in Git again?” | |
| 19 | + | |
| 20 | +This document’s authors are intimately familiar with Fossil, so it is | |
| 21 | +difficult for us to anticipate the perspective of people who are | |
| 22 | +intimately familiar with Git. If you have a lot of prior Git | |
| 23 | +experience, we welcome your contributions and questions on the [Fossil | |
| 24 | +Forum][ffor]. | |
| 27 | 25 | |
| 28 | 26 | While we do try to explain Fossil-specific terminology inline here |
| 29 | 27 | as-needed, you may find it helpful to skim [the Fossil glossary][gloss]. |
| 30 | 28 | It will give you another take on our definitions here, and it may help |
| 31 | 29 | you to understand some of the other Fossil docs better. |
| 32 | 30 | |
| 31 | +We focus more on practical command examples here than on [the | |
| 32 | +philosophical underpinnings][fvg] that drive these differences. | |
| 33 | 33 | |
| ----- | ||
| 34 | +[bis]: /help?cmd=bisect | |
| 35 | +[ffor]: https://fossil-scm.org/forum | |
| 36 | +[fvg]: ./fossil-v-git.wiki | |
| 34 | 37 | |
| 35 | 38 | |
| 36 | 39 | <a id="mwd"></a> |
| 37 | 40 | ## Repositories And Checkouts Are Distinct |
| 38 | 41 | |
| 39 | 42 | A repository and a check-out are distinct concepts in Fossil, whereas |
| 40 | -the two are collocated by default with Git. | |
| 41 | - | |
| 42 | -A Fossil repository is a SQLite database storing | |
| 43 | -the entire history of a project. A Fossil check-out is a | |
| 44 | -directory that contains a snapshot of your project that you | |
| 45 | -are currently working on, extracted for you from that database by the | |
| 46 | -`fossil` program. | |
| 47 | - | |
| 48 | -With Git, cloning a repository gets you what Fossil would call a | |
| 49 | -check-out directory with the repository stored in a `.git` subdirectory | |
| 50 | -of that check-out. There are methods to get additional working directories | |
| 51 | -pointing at that same Git repository, but because it’s not designed into | |
| 52 | -the core concept of the tool, Git tutorials usually advocate a | |
| 53 | -switch-in-place working mode instead, so that is how most users end up | |
| 54 | -working with it. | |
| 55 | - | |
| 56 | -You can use Fossil the same way, switching between versions in a | |
| 57 | -single check-out directory: | |
| 58 | - | |
| 59 | - fossil clone https://example.com/repo /path/to/repo.fossil | |
| 60 | - mkdir work-dir | |
| 61 | - cd work-dir | |
| 62 | - fossil open /path/to/repo.fossil | |
| 63 | - ...work on trunk... | |
| 64 | - fossil update my-other-branch # like “git checkout” | |
| 65 | - ...work on your other branch in the same directory... | |
| 66 | - | |
| 67 | -As of Fossil 2.12, you can ask it to clone-and-open into a single directory, as Git | |
| 68 | -always has done: | |
| 69 | - | |
| 70 | - mkdir work-dir | |
| 71 | - cd work-dir | |
| 72 | - fossil open https://example.com/repo | |
| 73 | - | |
| 74 | -Now you have “trunk” open in `work-dir`, with the repo file stored as | |
| 75 | -`repo.fossil` in that same directory. | |
| 76 | - | |
| 77 | -You may be expecting [`fossil clone`][clone] to create a directory for | |
| 78 | -you like Git does, but because the repository is separate from the | |
| 79 | -working directory, it does not do that, on purpose: you have to tell it | |
| 80 | -where to store the repository file. | |
| 81 | - | |
| 82 | -The [`fossil open URI`][open] syntax is our compromise for users wanting | |
| 83 | -a clone-and-open command. But, because Fossil’s `open` command | |
| 84 | -historically opens into the current directory, and it won’t open a | |
| 85 | -repository into a non-empty directory by default — as of Fossil 2.12, | |
| 86 | -anyway — you have to create the directory manually and `cd` into it | |
| 87 | -before opening it. If `fossil open URI` worked like `git clone`, that | |
| 88 | -would mean `fossil open` has two different ways of working depending on | |
| 89 | -the argument, which is a non-Fossil sort of thing to do. We strive for | |
| 90 | -consistent behavior across commands and modes. | |
| 91 | - | |
| 92 | -The Fossil repository file can be named anything you want, with a single | |
| 93 | -exception: if you’re going to use the [`fossil server DIRECTORY`][server] | |
| 94 | -feature, the repositories need to have a "`.fossil`" suffix. That aside, | |
| 95 | -you can follow any other convention that makes sense to you. | |
| 96 | - | |
| 97 | -Many Fossil users gather all of their Fossil repositories | |
| 98 | -in a single directory on their machine, such as "`~/museum`" or | |
| 99 | -"`C:\Fossils`". This can help humans to keep their repositories | |
| 100 | -organized, but Fossil itself doesn't really care. (Why “museum”? | |
| 101 | -Because that is where one stores valuable fossils.) | |
| 102 | - | |
| 103 | -Because Fossil cleanly separates the repository from the check-out, it | |
| 104 | -is routine to have multiple check-outs from the same repository: | |
| 105 | - | |
| 106 | - mkdir -p ~/src/my-project/trunk | |
| 107 | - cd ~/src/my-project/trunk | |
| 108 | - fossil open /path/to/repo.fossil # implicitly opens “trunk” | |
| 109 | - mkdir ../my-other-branch | |
| 110 | - cd ../my-other-branch | |
| 111 | - fossil open /path/to/repo.fossil my-other-branch | |
| 112 | - mkdir ../release | |
| 113 | - cd ../release | |
| 114 | - fossil open /path/to/repo.fossil release | |
| 115 | - mkdir ../scratch | |
| 116 | - cd ../scratch | |
| 117 | - fossil open /path/to/repo.fossil abcd1234 | |
| 118 | - mkdir ../test | |
| 119 | - cd ../test | |
| 120 | - fossil open /path/to/repo.fossil 2019-04-01 | |
| 121 | - | |
| 122 | -Now you have five separate check-out directories: one each for trunk, an | |
| 123 | -alternate branch you’re working on, the latest tagged public release, a | |
| 124 | -“scratch” directory for experiments or brief bits of work you don’t want | |
| 125 | -to do in the other check-out directories, and a directory for testing a | |
| 126 | -user report of a bug in the trunk version as of last April Fool’s Day. | |
| 127 | -Each check-out operates independently of the others. | |
| 128 | - | |
| 129 | -This multiple-checkouts working style is especially useful when Fossil stores source code in programming languages | |
| 130 | -where there is a “build” step that transforms source files into files | |
| 131 | -you actually run or distribute. With Git’s typical switch-in-place workflow, | |
| 132 | -you have to rebuild all outputs from the source files | |
| 133 | -that differ between those versions whenever you switch versions. In the above Fossil working model, | |
| 134 | -you switch versions with a “`cd`” command instead, so that you only have | |
| 135 | -to rebuild outputs from files you yourself change. | |
| 136 | - | |
| 137 | -This style is also useful when a check-out directory may be tied up with | |
| 138 | -some long-running process, as with the “test” example above, where you | |
| 139 | -might need to run an hours-long brute-force replication script to tickle | |
| 140 | -a [Heisenbug][hb], forcing it to show itself. While that runs, you can | |
| 141 | -open a new terminal tab, “`cd ../trunk`”, and get back | |
| 142 | -to work. | |
| 143 | - | |
| 144 | -Git users may be initially confused by the `.fslckout` file at the root | |
| 145 | -of a check-out directory. | |
| 146 | -This is not the same thing as `.git`. It’s a per-checkout SQLite | |
| 43 | +the two are collocated by default with Git. This difference shows up in | |
| 44 | +several separate places when it comes to moving from Git to Fossil. | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | +#### <a id="cwork" name="scw"></a> Checkout Workflows | |
| 49 | + | |
| 50 | +A Fossil repository is a SQLite database storing the entire history of a | |
| 51 | +project. It is not normally stored inside the working tree. | |
| 52 | +A Fossil working tree — also called a check-out — is a directory | |
| 53 | +that contains a snapshot of your project that you are currently working | |
| 54 | +on, extracted for you from the repository database file by the `fossil` | |
| 55 | +program. | |
| 56 | + | |
| 57 | +Git commingles these two by default, with the repository stored in a | |
| 58 | +`.git` subdirectory underneath your working directory. There are ways to | |
| 59 | +[emulate the Fossil working style in Git](#worktree), but because they’re not | |
| 60 | +designed into the core concept of the tool, Git tutorials usually | |
| 61 | +advocate a switch-in-place working mode instead, so that is how most | |
| 62 | +users end up working with Git. Contrast [Fossil’s check-out workflow | |
| 63 | +document][ckwf] to see the practical differences. | |
| 64 | + | |
| 65 | +There is one Git-specific detail we wish to add beyond what that | |
| 66 | +document already covers. This command: | |
| 67 | + | |
| 68 | + git checkout some-branch | |
| 69 | + | |
| 70 | +…is best given as: | |
| 71 | + | |
| 72 | + fossil update some-branch | |
| 73 | + | |
| 74 | +…in Fossil. There is a `fossil checkout` command, but it has two | |
| 75 | +restrictions that push you toward using `fossil update` instead: | |
| 76 | + | |
| 77 | +1. Several features in `fossil update` do not exist in | |
| 78 | + `fossil checkout`. | |
| 79 | + | |
| 80 | +2. The lone exception is `fossil checkout --keep`, a rarely-needed | |
| 81 | + operation. | |
| 82 | + | |
| 83 | +3. Fossil will have you typing “`fossil up`” frequently anyway to pull | |
| 84 | + remote changes and merge them into the local check-out directory. | |
| 85 | + Adding a `VERSION` string for the cases where you mean something | |
| 86 | + other than “tip of the current branch” is an easy habit to develop. | |
| 87 | + | |
| 88 | +Neither command is an alias for the other. They overlap enough that they | |
| 89 | +can be used interchangeably for everyday use cases, but since `update` | |
| 90 | +is more powerful, we recommend that you break the habit of typing | |
| 91 | +`checkout`. | |
| 92 | + | |
| 93 | +[ckwf]: ./ckout-workflows.md | |
| 94 | + | |
| 95 | + | |
| 96 | +#### <a id="rname"></a> Naming Repositories | |
| 97 | + | |
| 98 | +The Fossil repository database file can be named anything | |
| 99 | +you want, with a single exception: if you’re going to use the | |
| 100 | +[`fossil server DIRECTORY`][server] feature, the repositories you wish | |
| 101 | +to serve need to be stored together in a flat directory and have | |
| 102 | +"`.fossil`" suffixes. That aside, you can follow any other convention that | |
| 103 | +makes sense to you. | |
| 104 | + | |
| 105 | +This author uses a scheme like the following on mobile machines that | |
| 106 | +shuttle between home and the office: | |
| 107 | + | |
| 108 | +``` pikchr toggle indent | |
| 109 | +box "~/museum/" fit | |
| 110 | +move right 0.1 | |
| 111 | +line right dotted | |
| 112 | +move right 0.05 | |
| 113 | +box invis "where one stores valuable fossils" ljust | |
| 114 | + | |
| 115 | +arrow down 50% from first box.s then right 50% | |
| 116 | +box "work/" fit | |
| 117 | +move right 0.1 | |
| 118 | +line dotted | |
| 119 | +move right 0.05 | |
| 120 | +box invis "projects from $dayjob" ljust | |
| 121 | + | |
| 122 | +arrow down 50% from 2nd vertex of previous arrow then right 50% | |
| 123 | +box "home/" fit | |
| 124 | +move right 0.1 | |
| 125 | +line dotted right until even with previous line.end | |
| 126 | +move right 0.05 | |
| 127 | +box invis "personal at-home projects" ljust | |
| 128 | + | |
| 129 | +arrow down 50% from 2nd vertex of previous arrow then right 50% | |
| 130 | +box "other/" fit | |
| 131 | +move right 0.1 | |
| 132 | +line dotted right until even with previous line.end | |
| 133 | +move right 0.05 | |
| 134 | +box invis "clones of Fossil itself, SQLite, etc." ljust | |
| 135 | +``` | |
| 136 | + | |
| 137 | +On a Windows box, you might instead choose "`C:\Fossils`" | |
| 138 | +and do without the subdirectory scheme, for example. | |
| 139 | + | |
| 140 | + | |
| 141 | +#### <a id="close" name="dotfile"></a> Closing A Check-Out | |
| 142 | + | |
| 143 | +The [`fossil close`][close] command dissociates a check-out directory from the | |
| 144 | +Fossil repository database, nondestructively inverting [`fossil open`][open]. It | |
| 145 | +won’t remove the managed files, and unless you give the `--force` | |
| 146 | +option, it won’t let you close the check-out with uncommitted changes to | |
| 147 | +those managed files. | |
| 148 | + | |
| 149 | +The `close` command refuses to run without `--force` when you have | |
| 150 | +certain precious per-checkout data, which Fossil stores in the | |
| 151 | +`.fslckout` file at the root of a check-out directory. This is a SQLite | |
| 147 | 152 | database that keeps track of local state such as what version you have |
| 148 | 153 | checked out, the contents of the [stash] for that working directory, the |
| 149 | -[undo] buffers, per-checkout [settings][set], and so forth. Largely what Fossil | |
| 150 | -does when you ask it to [close] a check-out is to remove this file after | |
| 151 | -making certain safety checks. | |
| 154 | +[undo] buffers, per-checkout [settings][set], and so forth. The stash | |
| 155 | +and undo buffers are considered precious uncommitted changes, | |
| 156 | +so you have to force Fossil to discard these as part of closing the | |
| 157 | +check-out. | |
| 152 | 158 | |
| 153 | -(In native Windows builds of Fossil, this file is called `_FOSSIL_` | |
| 159 | +Thus, `.fslckout` is not the same thing as `.git`! | |
| 160 | + | |
| 161 | +In native Windows builds of Fossil — that is, excluding Cygwin and WSL | |
| 162 | +builds, which follow POSIX conventions — this file is called `_FOSSIL_` | |
| 154 | 163 | instead to get around the historical 3-character extension limit with |
| 155 | -certain legacy filesystems. “Native” here is a distinction to exclude | |
| 156 | -Cygwin and WSL builds, which use `.fslckout`.) | |
| 164 | +certain legacy filesystems. | |
| 165 | + | |
| 166 | +Closing a check-out directory is a rare operation. One use case | |
| 167 | +is that you’re about to delete the directory, so you want Fossil to forget about it | |
| 168 | +for the purposes of commands like [`fossil all`][all]. Even that isn’t | |
| 169 | +necessary, because Fossil will detect that this has happened and forget | |
| 170 | +the working directory for you. | |
| 171 | + | |
| 172 | +[all]: /help?cmd=all | |
| 173 | + | |
| 174 | + | |
| 175 | +#### <a id="worktree"></a> Git Worktrees | |
| 176 | + | |
| 177 | +There are at least three different ways to get [Fossil-style multiple | |
| 178 | +check-out directories][mcw] with Git. | |
| 179 | + | |
| 180 | +The old way is to simply symlink the `.git` directory between working | |
| 181 | +trees: | |
| 182 | + | |
| 183 | + mkdir ../foo-branch | |
| 184 | + ln -s ../actual-clone-dir/.git . | |
| 185 | + git checkout foo-branch | |
| 186 | + | |
| 187 | +The symlink trick has a number of problems, the largest being that | |
| 188 | +symlinks weren’t available on Windows until Vista, and until the Windows | |
| 189 | +10 Creators Update was released in spring of 2017, you had to be an | |
| 190 | +Administrator to use the feature besides. ([Source][wsyml]) Git solved | |
| 191 | +this problem two years earlier with the `git-worktree` command in Git | |
| 192 | +2.5: | |
| 193 | + | |
| 194 | + git worktree add ../foo-branch foo-branch | |
| 195 | + cd ../foo-branch | |
| 196 | + | |
| 197 | +That is approximately equivalent to this in Fossil: | |
| 198 | + | |
| 199 | + mkdir ../foo-branch | |
| 200 | + fossil open /path/to/repo.fossil foo-branch | |
| 201 | + | |
| 202 | +That then leads us to the closest equivalent in Git to [closing a Fossil | |
| 203 | +check-out](#close): | |
| 204 | + | |
| 205 | + git worktree remove . | |
| 206 | + | |
| 207 | +Note, however, that unlike `fossil close`, once the Git command | |
| 208 | +determines that there are no uncommitted changes, it blows away all of | |
| 209 | +the checked-out files! Fossil’s alternative is shorter, easier to | |
| 210 | +remember, and safer. | |
| 211 | + | |
| 212 | +There’s another way to get Fossil-like separate worktrees in Git: | |
| 213 | + | |
| 214 | + git clone --separate-git-dir repo.git https://example.com/repo | |
| 215 | + | |
| 216 | +This allows you to have your Git repository directory entirely separate | |
| 217 | +from your working tree, with `.git` in the check-out directory being a | |
| 218 | +file that points to `../repo.git`, in this example. | |
| 219 | + | |
| 220 | +As of Fossil 2.14, there is a direct equivalent: | |
| 221 | + | |
| 222 | + fossil clone https://example.com/repo | |
| 223 | + | |
| 224 | +It’s a shorter command because we deduce `repo.fossil` and the `repo/` | |
| 225 | +working directory from the last element of the path in the URI. If you | |
| 226 | +wanted to override both deductions, you’d say: | |
| 227 | + | |
| 228 | + fossil clone --workdir foo https://example.com/repo/bar | |
| 229 | + | |
| 230 | +That gets you `bar.fossil` with a `foo/` working directory alongside it. | |
| 231 | + | |
| 232 | +[mcw]: ./ckout-workflows.md#mcw | |
| 233 | +[wsyml]: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ | |
| 234 | + | |
| 235 | + | |
| 236 | +#### <a id="iip"></a> Init In Place | |
| 237 | + | |
| 238 | +To illustrate the differences that Fossil’s separation of repository | |
| 239 | +from working directory creates in practice, consider this common Git “init in place” | |
| 240 | +method for creating a new repository from an existing tree of files, | |
| 241 | +perhaps because you are placing that project under version control for | |
| 242 | +the first time: | |
| 243 | + | |
| 244 | + cd long-established-project | |
| 245 | + git init | |
| 246 | + git add * | |
| 247 | + git commit -m "Initial commit of project." | |
| 248 | + | |
| 249 | +The closest equivalent in Fossil is: | |
| 250 | + | |
| 251 | + cd long-established-project | |
| 252 | + fossil init .fsl | |
| 253 | + fossil open --force .fsl | |
| 254 | + fossil add * | |
| 255 | + fossil ci -m "Initial commit of project." | |
| 256 | + | |
| 257 | +Note that unlike in Git, you can abbreviate the “`commit`” command in | |
| 258 | +Fossil as “`ci`” for compatibility with CVS, Subversion, etc. | |
| 259 | + | |
| 260 | +This creates a `.fsl` repo DB at the root of the project check-out to | |
| 261 | +emulate the `.git` repo dir. We have to use the `--force` flag on | |
| 262 | +opening the new repo because Fossil expects you to open a repo into an | |
| 263 | +empty directory in order to avoid spamming the contents of a repo over | |
| 264 | +an existing directory full of files. Here, we know the directory | |
| 265 | +contains files that will soon belong in the repository, though, so we | |
| 266 | +override this check. From then on, Fossil works like Git, for the | |
| 267 | +purposes of this example. | |
| 268 | + | |
| 269 | +We’ve drawn this example to create a tight parallel between Fossil and | |
| 270 | +Git, not to commend this `.fsl`-at-project-root trick to you. A better | |
| 271 | +choice would be `~/museum/home/long-established-project.fossil`, if | |
| 272 | +you’re following [the directory scheme exemplified above](#rname). That said, it | |
| 273 | +does emphasize an earlier point: Fossil doesn’t care where you put the | |
| 274 | +repo DB file or what you name it. | |
| 275 | + | |
| 157 | 276 | |
| 158 | 277 | [clone]: /help?cmd=clone |
| 159 | 278 | [close]: /help?cmd=close |
| 160 | 279 | [gloss]: ./whyusefossil.wiki#definitions |
| 161 | -[hb]: https://en.wikipedia.org/wiki/Heisenbug | |
| 162 | 280 | [open]: /help?cmd=open |
| 163 | 281 | [set]: /help?cmd=setting |
| 164 | 282 | [server]: /help?cmd=server |
| 165 | 283 | [stash]: /help?cmd=stash |
| 166 | 284 | [undo]: /help?cmd=undo |
| 167 | 285 | |
| 168 | 286 | |
| 169 | -## <a id="log"></a> Fossil’s Timeline is the “Log” | |
| 287 | +## <a id="log"></a> Fossil’s Timeline Is The “Log” | |
| 170 | 288 | |
| 171 | -Git users often need to use the `git log` command to grovel through | |
| 172 | -commit histories due to its [weak data model][wdm]. | |
| 289 | +Git users often need to use the `git log` command to dig linearly through | |
| 290 | +commit histories due to its [weak data model][wdm], giving [O(n) | |
| 291 | +performance][ocomp]. | |
| 173 | 292 | |
| 174 | 293 | Fossil parses a huge amount of information out of commits that allow it |
| 175 | -to produce its [timeline CLI][tlc] and [its `/timeline` web view][tlw], | |
| 176 | -which generally have the info you would have to manually extract from | |
| 177 | -`git log`. | |
| 294 | +to produce its [timeline CLI][tlc] and [its `/timeline` web view][tlw] | |
| 295 | +using indexed SQL lookups, which generally have the info you would have | |
| 296 | +to manually extract from `git log`, produced much more quickly than Git | |
| 297 | +can, all else being equal: operations over [SQLite’s B-tree data structures][btree] | |
| 298 | +generally run in O(log n) time, faster than O(n) for equal *n* when the | |
| 299 | +constants are equal. Yet the constants are *not* equal because Fossil | |
| 300 | +reads from a single disk file rather than visit potentially many | |
| 301 | +files in sequence as Git must, so the OS’s buffer cache can result in | |
| 302 | +[still better performance][35pct]. | |
| 178 | 303 | |
| 179 | -[tlc]: /help?cmd=timeline | |
| 180 | -[tlw]: /help?cmd=/timeline | |
| 181 | -[wdm]: ./fossil-v-git.wiki#durable | |
| 304 | +Unlike Git’s log, Fossil’s timeline shows info across branches by | |
| 305 | +default, a feature for maintaining better situational awareness. The | |
| 306 | +`fossil timeline` command has no way to show a single branch’s commits, | |
| 307 | +but you can restrict your view like this using the web UI equivalent by | |
| 308 | +clicking the name of a branch on the `/timeline` or `/brlist` page. (Or | |
| 309 | +manually, by adding the `r=` query parameter.) Note that even in this | |
| 310 | +case, the Fossil timeline still shows other branches where they interact | |
| 311 | +with the one you’ve referenced in this way; again, better situational | |
| 312 | +awareness. | |
| 313 | + | |
| 314 | + | |
| 315 | +#### <a id="emu-log"></a> Emulating `git log` | |
| 316 | + | |
| 317 | +If you truly need a backwards-in-time-only view of history in Fossil to | |
| 318 | +emulate `git log`, this is as close as you can currently come: | |
| 319 | + | |
| 320 | + fossil timeline parents current | |
| 321 | + | |
| 322 | +Again, though, this isn’t restricted to a single branch, as `git log` | |
| 323 | +is. | |
| 324 | + | |
| 325 | +Another useful rough equivalent is: | |
| 326 | + | |
| 327 | + git log --raw | |
| 328 | + fossil time -v | |
| 329 | + | |
| 330 | +This shows what changed in each version, though Fossil’s view is more a | |
| 331 | +summary than a list of raw changes. To dig deeper into single commits, | |
| 332 | +you can use Fossil’s [`info` command][infoc] or its [`/info` view][infow]. | |
| 333 | + | |
| 334 | +Inversely, you may more exactly emulate the default `fossil timeline` | |
| 335 | +output with `git log --name-status`. | |
| 336 | + | |
| 337 | + | |
| 338 | +#### <a id="whatchanged"></a> What Changed? | |
| 339 | + | |
| 340 | +A related — though deprecated — command is `git whatchanged`, which gives results similar to | |
| 341 | +`git log --raw`, so we cover it here. | |
| 342 | + | |
| 343 | +Though there is no `fossil whatchanged` command, the same sort of | |
| 344 | +information is available. For example, to pull the current changes from | |
| 345 | +the remote repository and then inspect them before updating the local | |
| 346 | +working directory, you might say this in Git: | |
| 347 | + | |
| 348 | + git fetch | |
| 349 | + git whatchanged ..@{u} | |
| 350 | + | |
| 351 | +…which you can approximate in Fossil as: | |
| 352 | + | |
| 353 | + fossil pull | |
| 354 | + fossil up -n | |
| 355 | + fossil diff --from tip | |
| 356 | + | |
| 357 | +To invert the `diff` to show a more natural patch, the command needs to | |
| 358 | +be a bit more complicated, since you can’t currently give `--to` | |
| 359 | +without `--from`. | |
| 360 | + | |
| 361 | + fossil diff --from current --to tip | |
| 362 | + | |
| 363 | +Rather than use the “dry run” form of [the `update` command][up], you can | |
| 364 | +say: | |
| 365 | + | |
| 366 | + fossil timeline after current | |
| 367 | + | |
| 368 | +…or if you want to restrict the output to the current branch: | |
| 369 | + | |
| 370 | + fossil timeline descendants current | |
| 371 | + | |
| 372 | + | |
| 373 | +#### <a id="ckin-names"></a> Symbolic Check-In Names | |
| 374 | + | |
| 375 | +Note the use of [human-readable symbolic version names][scin] in Fossil | |
| 376 | +rather than [Git’s cryptic notations][gcn]. | |
| 377 | + | |
| 378 | +For a more dramatic example of this, let us ask Git, “What changed since the | |
| 379 | +beginning of last month?” being October 2020 as I write this: | |
| 380 | + | |
| 381 | + git log master@{2020-10-01}..HEAD | |
| 382 | + | |
| 383 | +That’s rather obscure! Fossil answers the same question with a simpler | |
| 384 | +command: | |
| 385 | + | |
| 386 | + fossil timeline after 2020-10-01 | |
| 387 | + | |
| 388 | +You may need to add `-n 0` to bypass the default output limit of | |
| 389 | +`fossil timeline`, 20 entries. Without that, this command reads | |
| 390 | +almost like English. | |
| 391 | + | |
| 392 | +Some Git users like to write commands like the above so: | |
| 393 | + | |
| 394 | + git log @{2020-10-01}..@ | |
| 395 | + | |
| 396 | +Is that better? “@” now means two different things: an at-time reference | |
| 397 | +and a shortcut for `HEAD`! | |
| 398 | + | |
| 399 | +If you are one of those that like short commands, Fossil’s method is | |
| 400 | +less cryptic: it lets you shorten words in most cases up to the point | |
| 401 | +that they become ambiguous. For example, you may abbreviate the last | |
| 402 | +`fossil` command in the prior section: | |
| 403 | + | |
| 404 | + fossil tim d c | |
| 405 | + | |
| 406 | +…beyond which the `timeline` command becomes ambiguous with `ticket`. | |
| 407 | + | |
| 408 | +Some Fossil users employ shell aliases, symlinks, or scripts to shorten | |
| 409 | +the command still further: | |
| 410 | + | |
| 411 | + alias f=fossil | |
| 412 | + f tim d c | |
| 413 | + | |
| 414 | +Granted, that’s rather obscure, but you you can also choose something | |
| 415 | +intermediate like “`f time desc curr`”, which is reasonably clear. | |
| 416 | + | |
| 417 | +[35pct]: https://www.sqlite.org/fasterthanfs.html | |
| 418 | +[btree]: https://sqlite.org/btreemodule.html | |
| 419 | +[gcn]: https://git-scm.com/docs/gitrevisions | |
| 420 | +[infoc]: /help?cmd=info | |
| 421 | +[infow]: /help?cmd=/info | |
| 422 | +[ocomp]: https://www.bigocheatsheet.com/ | |
| 423 | +[tlc]: /help?cmd=timeline | |
| 424 | +[tlw]: /help?cmd=/timeline | |
| 425 | +[up]: /help?cmd=update | |
| 426 | +[wdm]: ./fossil-v-git.wiki#durable | |
| 427 | + | |
| 428 | + | |
| 429 | +## <a id="dhead"></a> Detached HEAD State | |
| 430 | + | |
| 431 | +The SQL indexes in Fossil which we brought up above have a very useful | |
| 432 | +side benefit: you cannot have a [detached HEAD state][gdh] in Fossil, | |
| 433 | +the source of untold pain and data loss in Git. It simply cannot be done | |
| 434 | +in Fossil, because the indexes always let us find our way back into the | |
| 435 | +hash tree. | |
| 436 | + | |
| 437 | + | |
| 438 | +## <a id="slcom"></a> Summary Line Convention In Commit Comments | |
| 439 | + | |
| 440 | +The Git convention of a [length-limited summary line][lsl] at the start | |
| 441 | +of commit comments has no equivalent in Fossil. You’re welcome to style | |
| 442 | +your commit comments thus, but the convention isn’t used or enforced | |
| 443 | +anywhere in Fossil. For instance, setting `EDITOR=vim` and making a | |
| 444 | +commit doesn’t do syntax highlighting on the commit message to warn that | |
| 445 | +you’ve gone over the conventional limit on the first line, and the | |
| 446 | +Fossil web timeline display doesn’t show the summary line in bold. | |
| 447 | + | |
| 448 | +If you wish to follow such conventions in a Fossil project, you may want | |
| 449 | +to enable the “Allow block-markup in timeline” setting under Admin → | |
| 450 | +Timeline in the web UI to prevent Fossil from showing the message as a | |
| 451 | +single paragraph, sans line breaks. [Skin customization][cskin] would | |
| 452 | +allow you to style the first line of the commit message in bold in | |
| 453 | +`/timeline` views. | |
| 454 | + | |
| 455 | +[cskin]: ./customskin.md | |
| 456 | +[lsl]: https://chris.beams.io/posts/git-commit/#limit-50 | |
| 457 | + | |
| 182 | 458 | |
| 183 | 459 | |
| 184 | 460 | <a id="staging"></a> |
| 185 | 461 | ## There Is No Staging Area |
| 186 | 462 | |
| @@ -192,35 +467,40 @@ | ||
| 192 | 467 | If you only want to commit _some_ of the changes, list the names |
| 193 | 468 | of the files or directories you want to commit as arguments, like this: |
| 194 | 469 | |
| 195 | 470 | fossil commit src/feature.c doc/feature.md examples/feature |
| 196 | 471 | |
| 472 | +There are currently no interactive patching features in Fossil like | |
| 473 | +`git add --patch/-p` or `git commit -p`. [Contributions welcome!][ctrb] | |
| 474 | + | |
| 475 | +[ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki | |
| 476 | + | |
| 197 | 477 | |
| 198 | 478 | <a id="bneed"></a> |
| 199 | 479 | ## Create Branches At Point Of Need, Rather Than Ahead of Need |
| 200 | 480 | |
| 201 | 481 | Fossil prefers that you create new branches as part of the first commit |
| 202 | 482 | on that branch: |
| 203 | 483 | |
| 204 | - fossil commit --branch my-new-branch | |
| 484 | + fossil commit --branch my-new-branch | |
| 205 | 485 | |
| 206 | 486 | If that commit is successful, your local check-out directory is then |
| 207 | 487 | switched to the tip of that branch, so subsequent commits don’t need the |
| 208 | 488 | “`--branch`” option. You simply say `fossil commit` again to continue |
| 209 | 489 | adding commits to the tip of that branch. |
| 210 | 490 | |
| 211 | 491 | To switch back to the parent branch, say something like: |
| 212 | 492 | |
| 213 | - fossil update trunk # like “git checkout” | |
| 493 | + fossil update trunk # ≅ git checkout master | |
| 214 | 494 | |
| 215 | 495 | Fossil does also support the Git style, creating the branch ahead of |
| 216 | 496 | need: |
| 217 | 497 | |
| 218 | - fossil branch new my-new-branch | |
| 219 | - fossil update my-new-branch | |
| 220 | - ...work on first commit... | |
| 221 | - fossil commit | |
| 498 | + fossil branch new my-new-branch | |
| 499 | + fossil update my-new-branch | |
| 500 | + ...work on first commit... | |
| 501 | + fossil commit | |
| 222 | 502 | |
| 223 | 503 | This is more verbose, but it has the same effect: put the first commit |
| 224 | 504 | onto `my-new-branch` and switch the check-out directory to that branch so |
| 225 | 505 | subsequent commits are descendants of that initial branch commit. |
| 226 | 506 | |
| @@ -228,13 +508,14 @@ | ||
| 228 | 508 | *after* you commit it, using the "`fossil amend`" command. |
| 229 | 509 | For example: |
| 230 | 510 | |
| 231 | 511 | fossil amend current --branch my-new-branch |
| 232 | 512 | |
| 233 | -(“current” is one of the [special check-in names][scin] in Fossil. See | |
| 513 | +(The version string “current” is one of the [special check-in names][scin] in Fossil. See | |
| 234 | 514 | that document for the many other names you can give to “`amend`”, or |
| 235 | -indeed to any other Fossil command that accepts a “version” string.) | |
| 515 | +indeed to any other Fossil command documented to accept a `VERSION` or | |
| 516 | +`NAME` string.) | |
| 236 | 517 | |
| 237 | 518 | [scin]: ./checkin_names.wiki |
| 238 | 519 | |
| 239 | 520 | |
| 240 | 521 | <a id="autosync"></a> |
| @@ -264,11 +545,11 @@ | ||
| 264 | 545 | 2. It provides immediate off-machine backup of your commits. Unlike |
| 265 | 546 | centralized version control, though, you can still work while |
| 266 | 547 | disconnected; your changes will sync up with the remote once you get |
| 267 | 548 | back online. |
| 268 | 549 | |
| 269 | -3. Because there is little distinction betwen the clones in the Fossil | |
| 550 | +3. Because there is little distinction between the clones in the Fossil | |
| 270 | 551 | model — unlike in Git, where clones often quickly diverge from each |
| 271 | 552 | other, quite possibly on purpose — the backup advantage applies in inverse |
| 272 | 553 | as well: if the remote server falls over dead, one of those with a |
| 273 | 554 | clone of that repository can stand it back up, and everyone can get |
| 274 | 555 | back to work simply by re-pointing their local repo at the new |
| @@ -285,44 +566,49 @@ | ||
| 285 | 566 | |
| 286 | 567 | <a id="syncall"></a> |
| 287 | 568 | ## Sync Is All-Or-Nothing |
| 288 | 569 | |
| 289 | 570 | Fossil does not support the concept of syncing, pushing, or pulling |
| 290 | -individual branches. When you sync/push/pull in Fossil, you | |
| 291 | -sync/push/pull everything stored as artifacts in its hash tree: | |
| 571 | +individual branches. When you sync/push/pull in Fossil, it | |
| 572 | +processes all artifacts in its hash tree: | |
| 292 | 573 | branches, tags, wiki articles, tickets, forum posts, technotes… |
| 293 | -[Almost everything][bu]. | |
| 574 | +This is [not quite “everything,” full stop][bu], but it’s close. | |
| 294 | 575 | |
| 295 | 576 | Furthermore, branch *names* sync automatically in Fossil, not just the |
| 296 | -content of those branches. This means this common Git command: | |
| 577 | +content of those branches. That means this common Git command: | |
| 297 | 578 | |
| 298 | 579 | git push origin master |
| 299 | 580 | |
| 300 | -is simply this in Fossil: | |
| 581 | +…is simply this in Fossil: | |
| 301 | 582 | |
| 302 | 583 | fossil push |
| 303 | 584 | |
| 304 | 585 | Fossil doesn’t need to be told what to push or where to push it: it just |
| 305 | -keeps using the same remote server URL and branch name you gave it last, | |
| 306 | -until you tell it to do something different. | |
| 586 | +keeps using the same remote server URL you gave it last | |
| 587 | +until you [tell it to do something different][rem], and it pushes all | |
| 588 | +branches, not just one named local branch. | |
| 589 | + | |
| 590 | +[rem]: /help?cmd=remote | |
| 307 | 591 | |
| 308 | 592 | |
| 309 | 593 | <a id="trunk"></a> |
| 310 | 594 | ## The Main Branch Is Called "`trunk`" |
| 311 | 595 | |
| 312 | -In Fossil, the traditional name and the default name for the main branch | |
| 596 | +In Fossil, the default name for the main branch | |
| 313 | 597 | is "`trunk`". The "`trunk`" branch in Fossil corresponds to the |
| 314 | -"`master`" branch in stock Git or the "`main`" branch in GitHub. | |
| 598 | +"`master`" branch in stock Git or to [the “`main`” branch in GitHub][mbgh]. | |
| 315 | 599 | |
| 316 | 600 | Because the `fossil git export` command has to work with both stock Git |
| 317 | -and with GitHub, Fossil uses Git’s default: your Fossil repo’s “trunk” | |
| 318 | -branch becomes “master” on GitHub, not “main,” as in new GitHub repos. | |
| 319 | -It is not known what happens on subsequent exports if you | |
| 320 | -[later rename it][ghmain]. | |
| 601 | +and with GitHub, Fossil uses Git’s traditional default rather than | |
| 602 | +GitHub’s new default: your Fossil repo’s “trunk” branch becomes “master” | |
| 603 | +when [mirroring to GitHub][mirgh], not “main.” | |
| 321 | 604 | |
| 322 | -[6]: ./mirrortogithub.md | |
| 323 | -[ghmain]: https://github.com/github/renaming | |
| 605 | +We do not know what happens on subsequent exports if you later rename | |
| 606 | +this branch on the GitHub side. | |
| 607 | + | |
| 608 | +[mbgh]: https://github.com/github/renaming | |
| 609 | +[mirgh]: ./mirrortogithub.md | |
| 324 | 610 | |
| 325 | 611 | |
| 326 | 612 | <a id="unmanaged"></a> |
| 327 | 613 | ## The "`fossil status`" Command Does Not Show Unmanaged Files |
| 328 | 614 | |
| @@ -348,30 +634,106 @@ | ||
| 348 | 634 | come up with a new objection that we haven’t already considered and |
| 349 | 635 | addressed there. |
| 350 | 636 | |
| 351 | 637 | [3]: ./rebaseharm.md |
| 352 | 638 | |
| 639 | + | |
| 640 | +## <a id="show"></a> Showing Information About Commits | |
| 641 | + | |
| 642 | +While there is no direct equivalent to Git’s “`show`” command, similar | |
| 643 | +functionality may be present in Fossil under other commands: | |
| 644 | + | |
| 645 | + | |
| 646 | +#### <a name="patch"></a> Show A Patch For A Commit | |
| 647 | + | |
| 648 | + git show -p COMMIT_ID | |
| 649 | + | |
| 650 | +…gives much the same output as | |
| 651 | + | |
| 652 | + fossil diff --checkin COMMIT_ID | |
| 653 | + | |
| 654 | +…only without the patch email header. Git comes out of the [LKML] world, | |
| 655 | +where emailing a patch is a normal thing to do. Fossil is [designed for | |
| 656 | +cohesive teams][devorg] where such drive-by patches are rarer. | |
| 657 | + | |
| 658 | +You can use any of [Fossil’s special check-in names][scin] in place of | |
| 659 | +the `COMMIT_ID` in this and later examples. Fossil docs usually say | |
| 660 | +“`VERSION`” or “`NAME`” where this is allowed, since the version string | |
| 661 | +or name might not refer to a commit ID, but instead to a forum post, a | |
| 662 | +wiki document, etc. The following command answers the question “What did | |
| 663 | +I just commit?” | |
| 664 | + | |
| 665 | + fossil diff --checkin tip | |
| 666 | + | |
| 667 | +[devorg]: ./fossil-v-git.wiki#devorg | |
| 668 | +[LKML]: https://lkml.org/ | |
| 669 | + | |
| 670 | + | |
| 671 | +#### <a name="cmsg"></a> Show A Specific Commit Message | |
| 672 | + | |
| 673 | + git show -s COMMIT_ID | |
| 674 | + | |
| 675 | + | |
| 676 | +…is | |
| 677 | + | |
| 678 | + fossil time -n 1 COMMIT_ID | |
| 679 | + | |
| 680 | +…or with a shorter, more obvious command, though with more verbose output: | |
| 681 | + | |
| 682 | + fossil info COMMIT_ID | |
| 683 | + | |
| 684 | +The `fossil info` command isn’t otherwise a good equivalent to | |
| 685 | +`git show`; it just overlaps its functionality in some areas. Much of | |
| 686 | +what’s missing is present in the corresponding [`/info` web | |
| 687 | +view][infow], though. | |
| 688 | + | |
| 689 | + | |
| 690 | +#### <a name="dstat"></a> Diff Statistics | |
| 691 | + | |
| 692 | +Fossil doesn’t have an internal equivalent to commands like | |
| 693 | +`git show --stat`, but it’s easily remedied by using | |
| 694 | +[the widely-available `diffstat` tool][dst]: | |
| 695 | + | |
| 696 | + fossil diff -i --from 2020-04-01 | diffstat | |
| 697 | + | |
| 698 | +We gave the `-i` flag here to force Fossil to use its internal diff | |
| 699 | +implementation, bypassing [your local `diff-command` setting][dcset]. | |
| 700 | +If you had that set to [`colordiff`][cdiff], for example, its output | |
| 701 | +would confuse `diffstat`. | |
| 702 | + | |
| 703 | +[cdiff]: https://www.colordiff.org/ | |
| 704 | +[dcset]: https://fossil-scm.org/home/help?cmd=diff-command | |
| 705 | +[dst]: https://invisible-island.net/diffstat/diffstat.html | |
| 706 | + | |
| 353 | 707 | |
| 354 | 708 | <a id="btnames"></a> |
| 355 | -## Branch and Tag Names | |
| 709 | +## Branch And Tag Names | |
| 356 | 710 | |
| 357 | 711 | Fossil has no special restrictions on the names of tags and branches, |
| 358 | -though you might want to keep [Git's tag and branch name restrictions][4] | |
| 359 | -in mind if you plan on mirroring your Fossil repository to GitHub. | |
| 360 | - | |
| 361 | -[4]: https://git-scm.com/docs/git-check-ref-format | |
| 712 | +though you might want to keep [Git's tag and branch name restrictions][gcrf] | |
| 713 | +in mind if you plan on [mirroring your Fossil repository to GitHub][mirgh]. | |
| 362 | 714 | |
| 363 | 715 | Fossil does not require tag and branch names to be unique. It is |
| 364 | 716 | common, for example, to put a "`release`" tag on every release for a |
| 365 | 717 | Fossil-hosted project. This does not create a conflict in Fossil, since |
| 366 | -Fossil resolves such conflicts in a predictable way: the newest match | |
| 718 | +Fossil resolves the ambiguity in a predictable way: the newest match | |
| 367 | 719 | wins. Therefore, “`fossil up release`” always gets you the current |
| 368 | 720 | release in a project that uses this tagging convention. |
| 369 | 721 | |
| 722 | +[The `fossil git export` command][fge] squashes repeated tags down to a | |
| 723 | +single instance to avoid confusing Git, exporting only the newest tag, | |
| 724 | +emulating Fossil’s own ambiguity resolution rule as best it can within | |
| 725 | +Git’s limitations. | |
| 726 | + | |
| 727 | +[fge]: /help?cmd=git | |
| 728 | +[gcrf]: https://git-scm.com/docs/git-check-ref-format | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 370 | 732 | |
| 371 | 733 | <a id="cpickrev"></a> |
| 372 | -## Cherry-Picking and Reverting Commits | |
| 734 | +## Cherry-Picking And Reverting Commits | |
| 373 | 735 | |
| 374 | 736 | Git’s separate "`git cherry-pick`" and “`git revert`” commands are |
| 375 | 737 | options to the [`fossil merge` command][merge]: `--cherrypick` and |
| 376 | 738 | `--backout`, respectively. |
| 377 | 739 | |
| @@ -390,35 +752,175 @@ | ||
| 390 | 752 | default: they do not actually rename or delete the files in your |
| 391 | 753 | check-out. |
| 392 | 754 | |
| 393 | 755 | If you don’t like that default, you can change it globally: |
| 394 | 756 | |
| 395 | - fossil setting --global mv-rm-files 1 | |
| 757 | + fossil setting --global mv-rm-files 1 | |
| 396 | 758 | |
| 397 | 759 | Now these commands behave like in Git in any Fossil repository where |
| 398 | 760 | this setting hasn’t been overridden locally. |
| 399 | 761 | |
| 400 | 762 | If you want to keep Fossil’s soft `mv/rm` behavior most of the time, you |
| 401 | 763 | can cast it away on a per-command basis: |
| 402 | 764 | |
| 403 | - fossil mv --hard old-name new-name | |
| 765 | + fossil mv --hard old-name new-name | |
| 404 | 766 | |
| 405 | 767 | [mv]: /help?cmd=mv |
| 406 | 768 | [rm]: /help?cmd=rm |
| 407 | 769 | |
| 408 | 770 | |
| 409 | 771 | ---- |
| 410 | 772 | |
| 411 | 773 | |
| 412 | -<a id="morigin"></a> | |
| 413 | -## Multiple "origin" Servers | |
| 414 | - | |
| 415 | -In this final section of the document, we’ll go into a lot more detail | |
| 416 | -to illustrate the points above, not just give a quick summary of this | |
| 417 | -single difference. | |
| 418 | - | |
| 419 | -Consider a common use case at the time of this writing — during the | |
| 774 | +## <a id="cvdate" name="cs1"></a> Case Study 1: Checking Out A Version By Date | |
| 775 | + | |
| 776 | +Let’s get into something a bit more complicated: a case study showing | |
| 777 | +how the concepts lined out above cause Fossil to materially differ in | |
| 778 | +day-to-day operation from Git. | |
| 779 | + | |
| 780 | +Why would you want to check out a version of a project by date? Perhaps | |
| 781 | +because your customer gave you a vague bug report referencing only a | |
| 782 | +date rather than a version. Or, you may be poking semi-randomly through | |
| 783 | +history to find a “good” version to anchor the start point of a | |
| 784 | +[`bisect`][bis] operation. | |
| 785 | + | |
| 786 | +My search engine’s first result for “git checkout by date” is [this | |
| 787 | +highly-upvoted accepted Stack Overflow answer][gcod]. The first command | |
| 788 | +it gives is based on Git’s [`rev-parse` feature][grp]: | |
| 789 | + | |
| 790 | + git checkout master@{2020-03-17} | |
| 791 | + | |
| 792 | +There are a number of weaknesses in this command. From least to most | |
| 793 | +critical: | |
| 794 | + | |
| 795 | +1. It’s a bit cryptic. Leave off the refname or punctuation, and it | |
| 796 | + means something else. You cannot simplify the cryptic incantation in | |
| 797 | + the typical use case. | |
| 798 | + | |
| 799 | +2. A date string in Git without a time will be interpreted as | |
| 800 | + “[at localtime on that date][gapxd],” so the command means something | |
| 801 | + different from one second to the next! If there are multiple commits | |
| 802 | + on that date, that command can give different results depending on | |
| 803 | + the time of day you run it. | |
| 804 | + | |
| 805 | +3. It gives misleading output if there is no close match for the date | |
| 806 | + in target commit in the local [reflog]. On a fresh clone, the reflog | |
| 807 | + is empty, and even on a well-established clone, Git [automatically | |
| 808 | + prunes][gle] the reflog to 90 days of history by default. This means | |
| 809 | + the command above can give different results from one machine to the | |
| 810 | + next, or even from one day to the next on the same clone. | |
| 811 | + | |
| 812 | + The command won’t fail outright if the reflog can’t resolve the | |
| 813 | + given date: it simply gives the closest commit it can come up with, | |
| 814 | + even if it’s months or years out from your target! Sometimes it | |
| 815 | + gives a warning about the reflog not going back far enough to give a | |
| 816 | + useful result, and sometimes it doesn’t. If you’re on a fresh clone, | |
| 817 | + you are likely to get the “tip” commit’s revision ID no matter what | |
| 818 | + date value you give. | |
| 819 | + | |
| 820 | + Git tries its best, but because it’s working from a purgeable and | |
| 821 | + possibly-stale local cache, you cannot trust its results. | |
| 822 | + | |
| 823 | +We cannot recommend this command at all. It’s unreliable even in the | |
| 824 | +best case. | |
| 825 | + | |
| 826 | +That same Stack Overflow answer therefore goes on to recommend an | |
| 827 | +entirely different command: | |
| 828 | + | |
| 829 | + git checkout $(git rev-list -n 1 --first-parent --before="2020-03-17" master) | |
| 830 | + | |
| 831 | +We believe you get such answers to Git help requests in part | |
| 832 | +because of its lack of an always-up-to-date [index into its log](#log) and in | |
| 833 | +part because of its “small tools loosely joined” design philosophy. This | |
| 834 | +sort of command is therefore composed piece by piece: | |
| 835 | + | |
| 836 | +<center>◆ ◆ ◆</center> | |
| 837 | + | |
| 838 | +“Oh, I know, I’ll search the rev-list, which outputs commit IDs by | |
| 839 | +parsing the log backwards from `HEAD`! Easy!” | |
| 840 | + | |
| 841 | + git rev-list --before=2020-03-17 | |
| 842 | + | |
| 843 | +“Blast! Forgot the commit ID!” | |
| 844 | + | |
| 845 | + git rev-list --before=2020-03-17 master | |
| 846 | + | |
| 847 | +“Double blast! It just spammed my terminal with revision IDs! I need to | |
| 848 | +limit it to the single closest match: | |
| 849 | + | |
| 850 | + git rev-list -n 1 --before=2020-03-17 master | |
| 851 | + | |
| 852 | +“Okay, it gives me a single revision ID now, but is it what I’m after? | |
| 853 | +Let’s take a look…” | |
| 854 | + | |
| 855 | + git show $(git rev-list -n 1 --before=2020-03-17 master) | |
| 856 | + | |
| 857 | +“Oops, that’s giving me a merge commit, not what I want. | |
| 858 | +Off to search the web… Okay, it says I need to give either the | |
| 859 | +`--first-parent` or `--no-merges` flag to show only regular commits, | |
| 860 | +not merge-commits. Let’s try the first one:” | |
| 861 | + | |
| 862 | + git show $(git rev-list -n 1 --first-parent --before=2020-03-17 master) | |
| 863 | + | |
| 864 | +“Better. Let’s check it out:” | |
| 865 | + | |
| 866 | + git checkout $(git rev-list -n 1 --first-parent --before=2020-03-17 master) | |
| 867 | + | |
| 868 | +“Success, I guess?” | |
| 869 | + | |
| 870 | +<center>◆ ◆ ◆</center> | |
| 871 | + | |
| 872 | +This vignette is meant to explain some of Git’s popularity: it rewards | |
| 873 | +the sort of people who enjoy puzzles, many of whom are software | |
| 874 | +developers and thus need a tool like Git. Too bad if you’re just a | |
| 875 | +normal user. | |
| 876 | + | |
| 877 | +And too bad if you’re a Windows user who doesn’t want to use [Git | |
| 878 | +Bash][gbash], since neither of the stock OS command shells have a | |
| 879 | +command interpolation feature needed to run that horrid command. | |
| 880 | + | |
| 881 | +This alternative command still has weakness #2 above: if you run the | |
| 882 | +second `git show` command above on [Git’s own repository][gitgh], your | |
| 883 | +results may vary because there were four non-merge commits to Git on the | |
| 884 | +17th of March, 2020. | |
| 885 | + | |
| 886 | +You may be asking with an exasperated huff, “What is your *point*, man?” | |
| 887 | +The point is that the equivalent in Fossil is simply: | |
| 888 | + | |
| 889 | + fossil up 2020-03-17 | |
| 890 | + | |
| 891 | +…which will *always* give the commit closest to midnight UTC on the 17th | |
| 892 | +of March, 2020, no matter whether you do it on a fresh clone or a stale | |
| 893 | +one. The answer won’t shift about from one clone to the next or from | |
| 894 | +one local time of day to the next. We owe this reliability and stability | |
| 895 | +to three Fossil design choices: | |
| 896 | + | |
| 897 | +* Parse timestamps from all commits on clone into a local commit index, | |
| 898 | + then maintain that index through subsequent commits and syncs. | |
| 899 | + | |
| 900 | +* Use an indexed SQL `ORDER BY` query to match timestamps to commit | |
| 901 | + IDs for a fast and consistent result. | |
| 902 | + | |
| 903 | +* Round timestamp strings up using [rules][frud] consistent across | |
| 904 | + computers and local time of day. | |
| 905 | + | |
| 906 | +[frud]: https://fossil-scm.org/home/file/src/name.c?ci=d2a59b03727bc3&ln=122-141 | |
| 907 | +[gbash]: https://appuals.com/what-is-git-bash/ | |
| 908 | +[gapxd]: https://github.com/git/git/blob/7f7ebe054a/date.c#L1298-L1300 | |
| 909 | +[gcod]: https://stackoverflow.com/a/6990682/142454 | |
| 910 | +[gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/ | |
| 911 | +[gitgh]: https://github.com/git/git/ | |
| 912 | +[gle]: https://git-scm.com/docs/git-reflog#_options_for_expire | |
| 913 | +[gmc]: https://github.com/git/git/commit/67b0a24910fbb23c8f5e7a2c61c339818bc68296 | |
| 914 | +[grp]: https://git-scm.com/docs/git-rev-parse | |
| 915 | +[reflog]: https://git-scm.com/docs/git-reflog | |
| 916 | + | |
| 917 | +---- | |
| 918 | + | |
| 919 | +## <a id="morigin" name="cs2"></a> Case Study 2: Multiple "origin" Servers | |
| 920 | + | |
| 921 | +Now let us consider a common use case at the time of this writing — during the | |
| 420 | 922 | COVID-19 pandemic — where you’re working from home a lot, going into the |
| 421 | 923 | office one part-day a week only to do things that have to be done |
| 422 | 924 | on-site at the office. Let us also say you have no remote |
| 423 | 925 | access back into the work LAN, such as because your site IT is paranoid |
| 424 | 926 | about security. You may still want off-machine backups of your commits |
| @@ -448,20 +950,20 @@ | ||
| 448 | 950 | |
| 449 | 951 | ssh my-nas.local 'git init --bare /SHARES/dayjob/repo.git' |
| 450 | 952 | git push --all ssh://my-nas.local//SHARES/dayjob/repo.git |
| 451 | 953 | |
| 452 | 954 | Realize that this is carefully optimized down to these two long |
| 453 | -commands. In practice, typing these commands by hand, from memory, we’d | |
| 454 | -expect a normal user to need to give four or more commands here instead. | |
| 955 | +commands. In practice, we’d expect a user typing these commands by hand from memory | |
| 956 | +to need to give four or more commands here instead. | |
| 455 | 957 | Packing the “`git init`” call into the “`ssh`” call is something more |
| 456 | 958 | often done in scripts and documentation examples than done interactively, |
| 457 | 959 | which then necessitates a third command before the push, “`exit`”. |
| 458 | 960 | There’s also a good chance that you’ll forget the need for the `--bare` |
| 459 | 961 | option here to avoid a fatal complaint from Git that the laptop can’t |
| 460 | 962 | push into a non-empty repo. If you fall into this trap, among the many |
| 461 | 963 | that Git lays for newbies, you have to nuke the incorrectly initted |
| 462 | -repo, search the web and docs to find out about `--bare`, and try again. | |
| 964 | +repo, search the web or Git man pages to find out about `--bare`, and try again. | |
| 463 | 965 | |
| 464 | 966 | Having navigated that little minefield, |
| 465 | 967 | we can tell Git that there is a second origin, a “home” repo in |
| 466 | 968 | addition to the named “work” repo we set up earlier: |
| 467 | 969 | |
| @@ -469,11 +971,11 @@ | ||
| 469 | 971 | git config master.remote home |
| 470 | 972 | |
| 471 | 973 | We don’t have to push or pull because the remote repo is a complete |
| 472 | 974 | clone of the repo on the laptop at this point, so we can just get to |
| 473 | 975 | work now, committing along the way to get our work safely off-machine |
| 474 | -and onto the NAS, like so: | |
| 976 | +and onto our home NAS, like so: | |
| 475 | 977 | |
| 476 | 978 | git add |
| 477 | 979 | git commit |
| 478 | 980 | git push |
| 479 | 981 | |
| @@ -493,38 +995,38 @@ | ||
| 493 | 995 | that when returning home, you’d have to manually reset the upstream |
| 494 | 996 | again. |
| 495 | 997 | |
| 496 | 998 | This example also shows a consequence of that fact that |
| 497 | 999 | [Git doesn’t sync branch names](#syncall): you have to keep repeating |
| 498 | -yourself, “master, master.” | |
| 1000 | +yourself like an obsequious supplicant: “Master, master.” Didn’t we | |
| 1001 | +invent computers to serve humans, rather than the other way around? | |
| 499 | 1002 | |
| 500 | 1003 | |
| 501 | 1004 | #### Fossil Method |
| 502 | 1005 | |
| 503 | -Now we’re going to do the same thing as above using Fossil. We’ve broken | |
| 504 | -the commands up into blocks corresponding to those above for comparison. | |
| 1006 | +Now we’re going to do the same thing using Fossil, with | |
| 1007 | +the commands arranged in blocks corresponding to those above for comparison. | |
| 505 | 1008 | |
| 506 | 1009 | We start the same way, cloning the work repo down to the laptop: |
| 507 | 1010 | |
| 508 | - mkdir repo | |
| 1011 | + fossil clone https://dev-server.example.com/repo | |
| 509 | 1012 | cd repo |
| 510 | - fossil open https://dev-server.example.com/repo | |
| 511 | 1013 | fossil remote add work https://dev-server.example.com/repo |
| 512 | 1014 | |
| 513 | -We’ve chosen the “`fossil open URI`” syntax here rather than separate | |
| 1015 | +We’ve chosen the new “`fossil clone URI`” syntax added in Fossil 2.14 rather than separate | |
| 514 | 1016 | `clone` and `open` commands to make the parallel with Git clearer. [See |
| 515 | 1017 | above](#mwd) for more on that topic. |
| 516 | 1018 | |
| 517 | -The final command is longer than the Git equivalent because | |
| 1019 | +Our [`remote` command][rem] is longer than the Git equivalent because | |
| 518 | 1020 | Fossil currently has no short command |
| 519 | 1021 | to rename an existing remote. Worse, unlike with Git, we can’t just keep |
| 520 | 1022 | using the default remote name because Fossil uses that slot in its |
| 521 | 1023 | configuration database to store the *current* remote name, so on |
| 522 | 1024 | switching from work to home, the home URL will overwrite the work URL if |
| 523 | 1025 | we don’t give it an explicit name first. |
| 524 | 1026 | |
| 525 | -So far, the Fossil commands are longer, but keep these costs in perspective: | |
| 1027 | +Although the Fossil commands are longer, so far, keep it in perspective: | |
| 526 | 1028 | they’re one-time setup costs, |
| 527 | 1029 | easily amortized to insignificance by the shorter day-to-day commands |
| 528 | 1030 | below. |
| 529 | 1031 | |
| 530 | 1032 | On first beginning to work from home, we reverse-clone the Fossil repo |
| 531 | 1033 |
| --- www/gitusers.md | |
| +++ www/gitusers.md | |
| @@ -1,187 +1,462 @@ | |
| 1 | # Hints For Users With Prior Git Experience |
| 2 | |
| 3 | This document is a semi-random collection of hints intended to help |
| 4 | new users of Fossil who have had prior exposure to Git. In other words, |
| 5 | this document tries to describe the differences in how Fossil works |
| 6 | from the perspective of Git users. |
| 7 | |
| 8 | |
| 9 | ## Help Improve This Document |
| 10 | |
| 11 | If you have a lot of prior Git experience, and you are new to Fossil |
| 12 | and are struggling with some concepts, please ask for help on the |
| 13 | [Fossil Forum][1]. The people who write this document are intimately |
| 14 | familiar with Fossil and less familiar with Git. It is difficult for |
| 15 | us to anticipate the perspective of people who are initimately familiar |
| 16 | with Git and less familiar with Fossil. Asking questions on the Forum |
| 17 | will help us to improve the document. |
| 18 | |
| 19 | [1]: https://fossil-scm.org/forum |
| 20 | |
| 21 | Specific suggestions on how to improve this document are also welcomed, |
| 22 | of course. |
| 23 | |
| 24 | |
| 25 | |
| 26 | ## <a id="term"></a> Terminology |
| 27 | |
| 28 | While we do try to explain Fossil-specific terminology inline here |
| 29 | as-needed, you may find it helpful to skim [the Fossil glossary][gloss]. |
| 30 | It will give you another take on our definitions here, and it may help |
| 31 | you to understand some of the other Fossil docs better. |
| 32 | |
| 33 | |
| ----- | |
| 34 | |
| 35 | |
| 36 | <a id="mwd"></a> |
| 37 | ## Repositories And Checkouts Are Distinct |
| 38 | |
| 39 | A repository and a check-out are distinct concepts in Fossil, whereas |
| 40 | the two are collocated by default with Git. |
| 41 | |
| 42 | A Fossil repository is a SQLite database storing |
| 43 | the entire history of a project. A Fossil check-out is a |
| 44 | directory that contains a snapshot of your project that you |
| 45 | are currently working on, extracted for you from that database by the |
| 46 | `fossil` program. |
| 47 | |
| 48 | With Git, cloning a repository gets you what Fossil would call a |
| 49 | check-out directory with the repository stored in a `.git` subdirectory |
| 50 | of that check-out. There are methods to get additional working directories |
| 51 | pointing at that same Git repository, but because it’s not designed into |
| 52 | the core concept of the tool, Git tutorials usually advocate a |
| 53 | switch-in-place working mode instead, so that is how most users end up |
| 54 | working with it. |
| 55 | |
| 56 | You can use Fossil the same way, switching between versions in a |
| 57 | single check-out directory: |
| 58 | |
| 59 | fossil clone https://example.com/repo /path/to/repo.fossil |
| 60 | mkdir work-dir |
| 61 | cd work-dir |
| 62 | fossil open /path/to/repo.fossil |
| 63 | ...work on trunk... |
| 64 | fossil update my-other-branch # like “git checkout” |
| 65 | ...work on your other branch in the same directory... |
| 66 | |
| 67 | As of Fossil 2.12, you can ask it to clone-and-open into a single directory, as Git |
| 68 | always has done: |
| 69 | |
| 70 | mkdir work-dir |
| 71 | cd work-dir |
| 72 | fossil open https://example.com/repo |
| 73 | |
| 74 | Now you have “trunk” open in `work-dir`, with the repo file stored as |
| 75 | `repo.fossil` in that same directory. |
| 76 | |
| 77 | You may be expecting [`fossil clone`][clone] to create a directory for |
| 78 | you like Git does, but because the repository is separate from the |
| 79 | working directory, it does not do that, on purpose: you have to tell it |
| 80 | where to store the repository file. |
| 81 | |
| 82 | The [`fossil open URI`][open] syntax is our compromise for users wanting |
| 83 | a clone-and-open command. But, because Fossil’s `open` command |
| 84 | historically opens into the current directory, and it won’t open a |
| 85 | repository into a non-empty directory by default — as of Fossil 2.12, |
| 86 | anyway — you have to create the directory manually and `cd` into it |
| 87 | before opening it. If `fossil open URI` worked like `git clone`, that |
| 88 | would mean `fossil open` has two different ways of working depending on |
| 89 | the argument, which is a non-Fossil sort of thing to do. We strive for |
| 90 | consistent behavior across commands and modes. |
| 91 | |
| 92 | The Fossil repository file can be named anything you want, with a single |
| 93 | exception: if you’re going to use the [`fossil server DIRECTORY`][server] |
| 94 | feature, the repositories need to have a "`.fossil`" suffix. That aside, |
| 95 | you can follow any other convention that makes sense to you. |
| 96 | |
| 97 | Many Fossil users gather all of their Fossil repositories |
| 98 | in a single directory on their machine, such as "`~/museum`" or |
| 99 | "`C:\Fossils`". This can help humans to keep their repositories |
| 100 | organized, but Fossil itself doesn't really care. (Why “museum”? |
| 101 | Because that is where one stores valuable fossils.) |
| 102 | |
| 103 | Because Fossil cleanly separates the repository from the check-out, it |
| 104 | is routine to have multiple check-outs from the same repository: |
| 105 | |
| 106 | mkdir -p ~/src/my-project/trunk |
| 107 | cd ~/src/my-project/trunk |
| 108 | fossil open /path/to/repo.fossil # implicitly opens “trunk” |
| 109 | mkdir ../my-other-branch |
| 110 | cd ../my-other-branch |
| 111 | fossil open /path/to/repo.fossil my-other-branch |
| 112 | mkdir ../release |
| 113 | cd ../release |
| 114 | fossil open /path/to/repo.fossil release |
| 115 | mkdir ../scratch |
| 116 | cd ../scratch |
| 117 | fossil open /path/to/repo.fossil abcd1234 |
| 118 | mkdir ../test |
| 119 | cd ../test |
| 120 | fossil open /path/to/repo.fossil 2019-04-01 |
| 121 | |
| 122 | Now you have five separate check-out directories: one each for trunk, an |
| 123 | alternate branch you’re working on, the latest tagged public release, a |
| 124 | “scratch” directory for experiments or brief bits of work you don’t want |
| 125 | to do in the other check-out directories, and a directory for testing a |
| 126 | user report of a bug in the trunk version as of last April Fool’s Day. |
| 127 | Each check-out operates independently of the others. |
| 128 | |
| 129 | This multiple-checkouts working style is especially useful when Fossil stores source code in programming languages |
| 130 | where there is a “build” step that transforms source files into files |
| 131 | you actually run or distribute. With Git’s typical switch-in-place workflow, |
| 132 | you have to rebuild all outputs from the source files |
| 133 | that differ between those versions whenever you switch versions. In the above Fossil working model, |
| 134 | you switch versions with a “`cd`” command instead, so that you only have |
| 135 | to rebuild outputs from files you yourself change. |
| 136 | |
| 137 | This style is also useful when a check-out directory may be tied up with |
| 138 | some long-running process, as with the “test” example above, where you |
| 139 | might need to run an hours-long brute-force replication script to tickle |
| 140 | a [Heisenbug][hb], forcing it to show itself. While that runs, you can |
| 141 | open a new terminal tab, “`cd ../trunk`”, and get back |
| 142 | to work. |
| 143 | |
| 144 | Git users may be initially confused by the `.fslckout` file at the root |
| 145 | of a check-out directory. |
| 146 | This is not the same thing as `.git`. It’s a per-checkout SQLite |
| 147 | database that keeps track of local state such as what version you have |
| 148 | checked out, the contents of the [stash] for that working directory, the |
| 149 | [undo] buffers, per-checkout [settings][set], and so forth. Largely what Fossil |
| 150 | does when you ask it to [close] a check-out is to remove this file after |
| 151 | making certain safety checks. |
| 152 | |
| 153 | (In native Windows builds of Fossil, this file is called `_FOSSIL_` |
| 154 | instead to get around the historical 3-character extension limit with |
| 155 | certain legacy filesystems. “Native” here is a distinction to exclude |
| 156 | Cygwin and WSL builds, which use `.fslckout`.) |
| 157 | |
| 158 | [clone]: /help?cmd=clone |
| 159 | [close]: /help?cmd=close |
| 160 | [gloss]: ./whyusefossil.wiki#definitions |
| 161 | [hb]: https://en.wikipedia.org/wiki/Heisenbug |
| 162 | [open]: /help?cmd=open |
| 163 | [set]: /help?cmd=setting |
| 164 | [server]: /help?cmd=server |
| 165 | [stash]: /help?cmd=stash |
| 166 | [undo]: /help?cmd=undo |
| 167 | |
| 168 | |
| 169 | ## <a id="log"></a> Fossil’s Timeline is the “Log” |
| 170 | |
| 171 | Git users often need to use the `git log` command to grovel through |
| 172 | commit histories due to its [weak data model][wdm]. |
| 173 | |
| 174 | Fossil parses a huge amount of information out of commits that allow it |
| 175 | to produce its [timeline CLI][tlc] and [its `/timeline` web view][tlw], |
| 176 | which generally have the info you would have to manually extract from |
| 177 | `git log`. |
| 178 | |
| 179 | [tlc]: /help?cmd=timeline |
| 180 | [tlw]: /help?cmd=/timeline |
| 181 | [wdm]: ./fossil-v-git.wiki#durable |
| 182 | |
| 183 | |
| 184 | <a id="staging"></a> |
| 185 | ## There Is No Staging Area |
| 186 | |
| @@ -192,35 +467,40 @@ | |
| 192 | If you only want to commit _some_ of the changes, list the names |
| 193 | of the files or directories you want to commit as arguments, like this: |
| 194 | |
| 195 | fossil commit src/feature.c doc/feature.md examples/feature |
| 196 | |
| 197 | |
| 198 | <a id="bneed"></a> |
| 199 | ## Create Branches At Point Of Need, Rather Than Ahead of Need |
| 200 | |
| 201 | Fossil prefers that you create new branches as part of the first commit |
| 202 | on that branch: |
| 203 | |
| 204 | fossil commit --branch my-new-branch |
| 205 | |
| 206 | If that commit is successful, your local check-out directory is then |
| 207 | switched to the tip of that branch, so subsequent commits don’t need the |
| 208 | “`--branch`” option. You simply say `fossil commit` again to continue |
| 209 | adding commits to the tip of that branch. |
| 210 | |
| 211 | To switch back to the parent branch, say something like: |
| 212 | |
| 213 | fossil update trunk # like “git checkout” |
| 214 | |
| 215 | Fossil does also support the Git style, creating the branch ahead of |
| 216 | need: |
| 217 | |
| 218 | fossil branch new my-new-branch |
| 219 | fossil update my-new-branch |
| 220 | ...work on first commit... |
| 221 | fossil commit |
| 222 | |
| 223 | This is more verbose, but it has the same effect: put the first commit |
| 224 | onto `my-new-branch` and switch the check-out directory to that branch so |
| 225 | subsequent commits are descendants of that initial branch commit. |
| 226 | |
| @@ -228,13 +508,14 @@ | |
| 228 | *after* you commit it, using the "`fossil amend`" command. |
| 229 | For example: |
| 230 | |
| 231 | fossil amend current --branch my-new-branch |
| 232 | |
| 233 | (“current” is one of the [special check-in names][scin] in Fossil. See |
| 234 | that document for the many other names you can give to “`amend`”, or |
| 235 | indeed to any other Fossil command that accepts a “version” string.) |
| 236 | |
| 237 | [scin]: ./checkin_names.wiki |
| 238 | |
| 239 | |
| 240 | <a id="autosync"></a> |
| @@ -264,11 +545,11 @@ | |
| 264 | 2. It provides immediate off-machine backup of your commits. Unlike |
| 265 | centralized version control, though, you can still work while |
| 266 | disconnected; your changes will sync up with the remote once you get |
| 267 | back online. |
| 268 | |
| 269 | 3. Because there is little distinction betwen the clones in the Fossil |
| 270 | model — unlike in Git, where clones often quickly diverge from each |
| 271 | other, quite possibly on purpose — the backup advantage applies in inverse |
| 272 | as well: if the remote server falls over dead, one of those with a |
| 273 | clone of that repository can stand it back up, and everyone can get |
| 274 | back to work simply by re-pointing their local repo at the new |
| @@ -285,44 +566,49 @@ | |
| 285 | |
| 286 | <a id="syncall"></a> |
| 287 | ## Sync Is All-Or-Nothing |
| 288 | |
| 289 | Fossil does not support the concept of syncing, pushing, or pulling |
| 290 | individual branches. When you sync/push/pull in Fossil, you |
| 291 | sync/push/pull everything stored as artifacts in its hash tree: |
| 292 | branches, tags, wiki articles, tickets, forum posts, technotes… |
| 293 | [Almost everything][bu]. |
| 294 | |
| 295 | Furthermore, branch *names* sync automatically in Fossil, not just the |
| 296 | content of those branches. This means this common Git command: |
| 297 | |
| 298 | git push origin master |
| 299 | |
| 300 | is simply this in Fossil: |
| 301 | |
| 302 | fossil push |
| 303 | |
| 304 | Fossil doesn’t need to be told what to push or where to push it: it just |
| 305 | keeps using the same remote server URL and branch name you gave it last, |
| 306 | until you tell it to do something different. |
| 307 | |
| 308 | |
| 309 | <a id="trunk"></a> |
| 310 | ## The Main Branch Is Called "`trunk`" |
| 311 | |
| 312 | In Fossil, the traditional name and the default name for the main branch |
| 313 | is "`trunk`". The "`trunk`" branch in Fossil corresponds to the |
| 314 | "`master`" branch in stock Git or the "`main`" branch in GitHub. |
| 315 | |
| 316 | Because the `fossil git export` command has to work with both stock Git |
| 317 | and with GitHub, Fossil uses Git’s default: your Fossil repo’s “trunk” |
| 318 | branch becomes “master” on GitHub, not “main,” as in new GitHub repos. |
| 319 | It is not known what happens on subsequent exports if you |
| 320 | [later rename it][ghmain]. |
| 321 | |
| 322 | [6]: ./mirrortogithub.md |
| 323 | [ghmain]: https://github.com/github/renaming |
| 324 | |
| 325 | |
| 326 | <a id="unmanaged"></a> |
| 327 | ## The "`fossil status`" Command Does Not Show Unmanaged Files |
| 328 | |
| @@ -348,30 +634,106 @@ | |
| 348 | come up with a new objection that we haven’t already considered and |
| 349 | addressed there. |
| 350 | |
| 351 | [3]: ./rebaseharm.md |
| 352 | |
| 353 | |
| 354 | <a id="btnames"></a> |
| 355 | ## Branch and Tag Names |
| 356 | |
| 357 | Fossil has no special restrictions on the names of tags and branches, |
| 358 | though you might want to keep [Git's tag and branch name restrictions][4] |
| 359 | in mind if you plan on mirroring your Fossil repository to GitHub. |
| 360 | |
| 361 | [4]: https://git-scm.com/docs/git-check-ref-format |
| 362 | |
| 363 | Fossil does not require tag and branch names to be unique. It is |
| 364 | common, for example, to put a "`release`" tag on every release for a |
| 365 | Fossil-hosted project. This does not create a conflict in Fossil, since |
| 366 | Fossil resolves such conflicts in a predictable way: the newest match |
| 367 | wins. Therefore, “`fossil up release`” always gets you the current |
| 368 | release in a project that uses this tagging convention. |
| 369 | |
| 370 | |
| 371 | <a id="cpickrev"></a> |
| 372 | ## Cherry-Picking and Reverting Commits |
| 373 | |
| 374 | Git’s separate "`git cherry-pick`" and “`git revert`” commands are |
| 375 | options to the [`fossil merge` command][merge]: `--cherrypick` and |
| 376 | `--backout`, respectively. |
| 377 | |
| @@ -390,35 +752,175 @@ | |
| 390 | default: they do not actually rename or delete the files in your |
| 391 | check-out. |
| 392 | |
| 393 | If you don’t like that default, you can change it globally: |
| 394 | |
| 395 | fossil setting --global mv-rm-files 1 |
| 396 | |
| 397 | Now these commands behave like in Git in any Fossil repository where |
| 398 | this setting hasn’t been overridden locally. |
| 399 | |
| 400 | If you want to keep Fossil’s soft `mv/rm` behavior most of the time, you |
| 401 | can cast it away on a per-command basis: |
| 402 | |
| 403 | fossil mv --hard old-name new-name |
| 404 | |
| 405 | [mv]: /help?cmd=mv |
| 406 | [rm]: /help?cmd=rm |
| 407 | |
| 408 | |
| 409 | ---- |
| 410 | |
| 411 | |
| 412 | <a id="morigin"></a> |
| 413 | ## Multiple "origin" Servers |
| 414 | |
| 415 | In this final section of the document, we’ll go into a lot more detail |
| 416 | to illustrate the points above, not just give a quick summary of this |
| 417 | single difference. |
| 418 | |
| 419 | Consider a common use case at the time of this writing — during the |
| 420 | COVID-19 pandemic — where you’re working from home a lot, going into the |
| 421 | office one part-day a week only to do things that have to be done |
| 422 | on-site at the office. Let us also say you have no remote |
| 423 | access back into the work LAN, such as because your site IT is paranoid |
| 424 | about security. You may still want off-machine backups of your commits |
| @@ -448,20 +950,20 @@ | |
| 448 | |
| 449 | ssh my-nas.local 'git init --bare /SHARES/dayjob/repo.git' |
| 450 | git push --all ssh://my-nas.local//SHARES/dayjob/repo.git |
| 451 | |
| 452 | Realize that this is carefully optimized down to these two long |
| 453 | commands. In practice, typing these commands by hand, from memory, we’d |
| 454 | expect a normal user to need to give four or more commands here instead. |
| 455 | Packing the “`git init`” call into the “`ssh`” call is something more |
| 456 | often done in scripts and documentation examples than done interactively, |
| 457 | which then necessitates a third command before the push, “`exit`”. |
| 458 | There’s also a good chance that you’ll forget the need for the `--bare` |
| 459 | option here to avoid a fatal complaint from Git that the laptop can’t |
| 460 | push into a non-empty repo. If you fall into this trap, among the many |
| 461 | that Git lays for newbies, you have to nuke the incorrectly initted |
| 462 | repo, search the web and docs to find out about `--bare`, and try again. |
| 463 | |
| 464 | Having navigated that little minefield, |
| 465 | we can tell Git that there is a second origin, a “home” repo in |
| 466 | addition to the named “work” repo we set up earlier: |
| 467 | |
| @@ -469,11 +971,11 @@ | |
| 469 | git config master.remote home |
| 470 | |
| 471 | We don’t have to push or pull because the remote repo is a complete |
| 472 | clone of the repo on the laptop at this point, so we can just get to |
| 473 | work now, committing along the way to get our work safely off-machine |
| 474 | and onto the NAS, like so: |
| 475 | |
| 476 | git add |
| 477 | git commit |
| 478 | git push |
| 479 | |
| @@ -493,38 +995,38 @@ | |
| 493 | that when returning home, you’d have to manually reset the upstream |
| 494 | again. |
| 495 | |
| 496 | This example also shows a consequence of that fact that |
| 497 | [Git doesn’t sync branch names](#syncall): you have to keep repeating |
| 498 | yourself, “master, master.” |
| 499 | |
| 500 | |
| 501 | #### Fossil Method |
| 502 | |
| 503 | Now we’re going to do the same thing as above using Fossil. We’ve broken |
| 504 | the commands up into blocks corresponding to those above for comparison. |
| 505 | |
| 506 | We start the same way, cloning the work repo down to the laptop: |
| 507 | |
| 508 | mkdir repo |
| 509 | cd repo |
| 510 | fossil open https://dev-server.example.com/repo |
| 511 | fossil remote add work https://dev-server.example.com/repo |
| 512 | |
| 513 | We’ve chosen the “`fossil open URI`” syntax here rather than separate |
| 514 | `clone` and `open` commands to make the parallel with Git clearer. [See |
| 515 | above](#mwd) for more on that topic. |
| 516 | |
| 517 | The final command is longer than the Git equivalent because |
| 518 | Fossil currently has no short command |
| 519 | to rename an existing remote. Worse, unlike with Git, we can’t just keep |
| 520 | using the default remote name because Fossil uses that slot in its |
| 521 | configuration database to store the *current* remote name, so on |
| 522 | switching from work to home, the home URL will overwrite the work URL if |
| 523 | we don’t give it an explicit name first. |
| 524 | |
| 525 | So far, the Fossil commands are longer, but keep these costs in perspective: |
| 526 | they’re one-time setup costs, |
| 527 | easily amortized to insignificance by the shorter day-to-day commands |
| 528 | below. |
| 529 | |
| 530 | On first beginning to work from home, we reverse-clone the Fossil repo |
| 531 |
| --- www/gitusers.md | |
| +++ www/gitusers.md | |
| @@ -1,187 +1,462 @@ | |
| 1 | # Git to Fossil Translation Guide |
| 2 | |
| 3 | ## Introduction |
| 4 | |
| 5 | This document attempts to provide equivalents for common Git commands |
| 6 | and workflows where possible, and where not, to explain those cases. |
| 7 | |
| 8 | Although Fossil shares many similarities with Git, there are enough |
| 9 | differences that we can’t provide a simple “translation dictionary” for |
| 10 | some commands. This document is more concerned with those cases than the |
| 11 | simple 1:1 mappings, which you can likely find on your own. In many |
| 12 | cases, the sub-commands are identical: [`fossil bisect`][bis] does essentially |
| 13 | the same thing as `git bisect`, for example. |
| 14 | |
| 15 | We present this from the perspective of Git users moving to Fossil, but |
| 16 | it is also possible to read this document as a Fossil user who speaks |
| 17 | only pidgin Git, who may often have questions of the form, “Now how do I |
| 18 | do X in Git again?” |
| 19 | |
| 20 | This document’s authors are intimately familiar with Fossil, so it is |
| 21 | difficult for us to anticipate the perspective of people who are |
| 22 | intimately familiar with Git. If you have a lot of prior Git |
| 23 | experience, we welcome your contributions and questions on the [Fossil |
| 24 | Forum][ffor]. |
| 25 | |
| 26 | While we do try to explain Fossil-specific terminology inline here |
| 27 | as-needed, you may find it helpful to skim [the Fossil glossary][gloss]. |
| 28 | It will give you another take on our definitions here, and it may help |
| 29 | you to understand some of the other Fossil docs better. |
| 30 | |
| 31 | We focus more on practical command examples here than on [the |
| 32 | philosophical underpinnings][fvg] that drive these differences. |
| 33 | |
| ----- | |
| 34 | [bis]: /help?cmd=bisect |
| 35 | [ffor]: https://fossil-scm.org/forum |
| 36 | [fvg]: ./fossil-v-git.wiki |
| 37 | |
| 38 | |
| 39 | <a id="mwd"></a> |
| 40 | ## Repositories And Checkouts Are Distinct |
| 41 | |
| 42 | A repository and a check-out are distinct concepts in Fossil, whereas |
| 43 | the two are collocated by default with Git. This difference shows up in |
| 44 | several separate places when it comes to moving from Git to Fossil. |
| 45 | |
| 46 | |
| 47 | |
| 48 | #### <a id="cwork" name="scw"></a> Checkout Workflows |
| 49 | |
| 50 | A Fossil repository is a SQLite database storing the entire history of a |
| 51 | project. It is not normally stored inside the working tree. |
| 52 | A Fossil working tree — also called a check-out — is a directory |
| 53 | that contains a snapshot of your project that you are currently working |
| 54 | on, extracted for you from the repository database file by the `fossil` |
| 55 | program. |
| 56 | |
| 57 | Git commingles these two by default, with the repository stored in a |
| 58 | `.git` subdirectory underneath your working directory. There are ways to |
| 59 | [emulate the Fossil working style in Git](#worktree), but because they’re not |
| 60 | designed into the core concept of the tool, Git tutorials usually |
| 61 | advocate a switch-in-place working mode instead, so that is how most |
| 62 | users end up working with Git. Contrast [Fossil’s check-out workflow |
| 63 | document][ckwf] to see the practical differences. |
| 64 | |
| 65 | There is one Git-specific detail we wish to add beyond what that |
| 66 | document already covers. This command: |
| 67 | |
| 68 | git checkout some-branch |
| 69 | |
| 70 | …is best given as: |
| 71 | |
| 72 | fossil update some-branch |
| 73 | |
| 74 | …in Fossil. There is a `fossil checkout` command, but it has two |
| 75 | restrictions that push you toward using `fossil update` instead: |
| 76 | |
| 77 | 1. Several features in `fossil update` do not exist in |
| 78 | `fossil checkout`. |
| 79 | |
| 80 | 2. The lone exception is `fossil checkout --keep`, a rarely-needed |
| 81 | operation. |
| 82 | |
| 83 | 3. Fossil will have you typing “`fossil up`” frequently anyway to pull |
| 84 | remote changes and merge them into the local check-out directory. |
| 85 | Adding a `VERSION` string for the cases where you mean something |
| 86 | other than “tip of the current branch” is an easy habit to develop. |
| 87 | |
| 88 | Neither command is an alias for the other. They overlap enough that they |
| 89 | can be used interchangeably for everyday use cases, but since `update` |
| 90 | is more powerful, we recommend that you break the habit of typing |
| 91 | `checkout`. |
| 92 | |
| 93 | [ckwf]: ./ckout-workflows.md |
| 94 | |
| 95 | |
| 96 | #### <a id="rname"></a> Naming Repositories |
| 97 | |
| 98 | The Fossil repository database file can be named anything |
| 99 | you want, with a single exception: if you’re going to use the |
| 100 | [`fossil server DIRECTORY`][server] feature, the repositories you wish |
| 101 | to serve need to be stored together in a flat directory and have |
| 102 | "`.fossil`" suffixes. That aside, you can follow any other convention that |
| 103 | makes sense to you. |
| 104 | |
| 105 | This author uses a scheme like the following on mobile machines that |
| 106 | shuttle between home and the office: |
| 107 | |
| 108 | ``` pikchr toggle indent |
| 109 | box "~/museum/" fit |
| 110 | move right 0.1 |
| 111 | line right dotted |
| 112 | move right 0.05 |
| 113 | box invis "where one stores valuable fossils" ljust |
| 114 | |
| 115 | arrow down 50% from first box.s then right 50% |
| 116 | box "work/" fit |
| 117 | move right 0.1 |
| 118 | line dotted |
| 119 | move right 0.05 |
| 120 | box invis "projects from $dayjob" ljust |
| 121 | |
| 122 | arrow down 50% from 2nd vertex of previous arrow then right 50% |
| 123 | box "home/" fit |
| 124 | move right 0.1 |
| 125 | line dotted right until even with previous line.end |
| 126 | move right 0.05 |
| 127 | box invis "personal at-home projects" ljust |
| 128 | |
| 129 | arrow down 50% from 2nd vertex of previous arrow then right 50% |
| 130 | box "other/" fit |
| 131 | move right 0.1 |
| 132 | line dotted right until even with previous line.end |
| 133 | move right 0.05 |
| 134 | box invis "clones of Fossil itself, SQLite, etc." ljust |
| 135 | ``` |
| 136 | |
| 137 | On a Windows box, you might instead choose "`C:\Fossils`" |
| 138 | and do without the subdirectory scheme, for example. |
| 139 | |
| 140 | |
| 141 | #### <a id="close" name="dotfile"></a> Closing A Check-Out |
| 142 | |
| 143 | The [`fossil close`][close] command dissociates a check-out directory from the |
| 144 | Fossil repository database, nondestructively inverting [`fossil open`][open]. It |
| 145 | won’t remove the managed files, and unless you give the `--force` |
| 146 | option, it won’t let you close the check-out with uncommitted changes to |
| 147 | those managed files. |
| 148 | |
| 149 | The `close` command refuses to run without `--force` when you have |
| 150 | certain precious per-checkout data, which Fossil stores in the |
| 151 | `.fslckout` file at the root of a check-out directory. This is a SQLite |
| 152 | database that keeps track of local state such as what version you have |
| 153 | checked out, the contents of the [stash] for that working directory, the |
| 154 | [undo] buffers, per-checkout [settings][set], and so forth. The stash |
| 155 | and undo buffers are considered precious uncommitted changes, |
| 156 | so you have to force Fossil to discard these as part of closing the |
| 157 | check-out. |
| 158 | |
| 159 | Thus, `.fslckout` is not the same thing as `.git`! |
| 160 | |
| 161 | In native Windows builds of Fossil — that is, excluding Cygwin and WSL |
| 162 | builds, which follow POSIX conventions — this file is called `_FOSSIL_` |
| 163 | instead to get around the historical 3-character extension limit with |
| 164 | certain legacy filesystems. |
| 165 | |
| 166 | Closing a check-out directory is a rare operation. One use case |
| 167 | is that you’re about to delete the directory, so you want Fossil to forget about it |
| 168 | for the purposes of commands like [`fossil all`][all]. Even that isn’t |
| 169 | necessary, because Fossil will detect that this has happened and forget |
| 170 | the working directory for you. |
| 171 | |
| 172 | [all]: /help?cmd=all |
| 173 | |
| 174 | |
| 175 | #### <a id="worktree"></a> Git Worktrees |
| 176 | |
| 177 | There are at least three different ways to get [Fossil-style multiple |
| 178 | check-out directories][mcw] with Git. |
| 179 | |
| 180 | The old way is to simply symlink the `.git` directory between working |
| 181 | trees: |
| 182 | |
| 183 | mkdir ../foo-branch |
| 184 | ln -s ../actual-clone-dir/.git . |
| 185 | git checkout foo-branch |
| 186 | |
| 187 | The symlink trick has a number of problems, the largest being that |
| 188 | symlinks weren’t available on Windows until Vista, and until the Windows |
| 189 | 10 Creators Update was released in spring of 2017, you had to be an |
| 190 | Administrator to use the feature besides. ([Source][wsyml]) Git solved |
| 191 | this problem two years earlier with the `git-worktree` command in Git |
| 192 | 2.5: |
| 193 | |
| 194 | git worktree add ../foo-branch foo-branch |
| 195 | cd ../foo-branch |
| 196 | |
| 197 | That is approximately equivalent to this in Fossil: |
| 198 | |
| 199 | mkdir ../foo-branch |
| 200 | fossil open /path/to/repo.fossil foo-branch |
| 201 | |
| 202 | That then leads us to the closest equivalent in Git to [closing a Fossil |
| 203 | check-out](#close): |
| 204 | |
| 205 | git worktree remove . |
| 206 | |
| 207 | Note, however, that unlike `fossil close`, once the Git command |
| 208 | determines that there are no uncommitted changes, it blows away all of |
| 209 | the checked-out files! Fossil’s alternative is shorter, easier to |
| 210 | remember, and safer. |
| 211 | |
| 212 | There’s another way to get Fossil-like separate worktrees in Git: |
| 213 | |
| 214 | git clone --separate-git-dir repo.git https://example.com/repo |
| 215 | |
| 216 | This allows you to have your Git repository directory entirely separate |
| 217 | from your working tree, with `.git` in the check-out directory being a |
| 218 | file that points to `../repo.git`, in this example. |
| 219 | |
| 220 | As of Fossil 2.14, there is a direct equivalent: |
| 221 | |
| 222 | fossil clone https://example.com/repo |
| 223 | |
| 224 | It’s a shorter command because we deduce `repo.fossil` and the `repo/` |
| 225 | working directory from the last element of the path in the URI. If you |
| 226 | wanted to override both deductions, you’d say: |
| 227 | |
| 228 | fossil clone --workdir foo https://example.com/repo/bar |
| 229 | |
| 230 | That gets you `bar.fossil` with a `foo/` working directory alongside it. |
| 231 | |
| 232 | [mcw]: ./ckout-workflows.md#mcw |
| 233 | [wsyml]: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ |
| 234 | |
| 235 | |
| 236 | #### <a id="iip"></a> Init In Place |
| 237 | |
| 238 | To illustrate the differences that Fossil’s separation of repository |
| 239 | from working directory creates in practice, consider this common Git “init in place” |
| 240 | method for creating a new repository from an existing tree of files, |
| 241 | perhaps because you are placing that project under version control for |
| 242 | the first time: |
| 243 | |
| 244 | cd long-established-project |
| 245 | git init |
| 246 | git add * |
| 247 | git commit -m "Initial commit of project." |
| 248 | |
| 249 | The closest equivalent in Fossil is: |
| 250 | |
| 251 | cd long-established-project |
| 252 | fossil init .fsl |
| 253 | fossil open --force .fsl |
| 254 | fossil add * |
| 255 | fossil ci -m "Initial commit of project." |
| 256 | |
| 257 | Note that unlike in Git, you can abbreviate the “`commit`” command in |
| 258 | Fossil as “`ci`” for compatibility with CVS, Subversion, etc. |
| 259 | |
| 260 | This creates a `.fsl` repo DB at the root of the project check-out to |
| 261 | emulate the `.git` repo dir. We have to use the `--force` flag on |
| 262 | opening the new repo because Fossil expects you to open a repo into an |
| 263 | empty directory in order to avoid spamming the contents of a repo over |
| 264 | an existing directory full of files. Here, we know the directory |
| 265 | contains files that will soon belong in the repository, though, so we |
| 266 | override this check. From then on, Fossil works like Git, for the |
| 267 | purposes of this example. |
| 268 | |
| 269 | We’ve drawn this example to create a tight parallel between Fossil and |
| 270 | Git, not to commend this `.fsl`-at-project-root trick to you. A better |
| 271 | choice would be `~/museum/home/long-established-project.fossil`, if |
| 272 | you’re following [the directory scheme exemplified above](#rname). That said, it |
| 273 | does emphasize an earlier point: Fossil doesn’t care where you put the |
| 274 | repo DB file or what you name it. |
| 275 | |
| 276 | |
| 277 | [clone]: /help?cmd=clone |
| 278 | [close]: /help?cmd=close |
| 279 | [gloss]: ./whyusefossil.wiki#definitions |
| 280 | [open]: /help?cmd=open |
| 281 | [set]: /help?cmd=setting |
| 282 | [server]: /help?cmd=server |
| 283 | [stash]: /help?cmd=stash |
| 284 | [undo]: /help?cmd=undo |
| 285 | |
| 286 | |
| 287 | ## <a id="log"></a> Fossil’s Timeline Is The “Log” |
| 288 | |
| 289 | Git users often need to use the `git log` command to dig linearly through |
| 290 | commit histories due to its [weak data model][wdm], giving [O(n) |
| 291 | performance][ocomp]. |
| 292 | |
| 293 | Fossil parses a huge amount of information out of commits that allow it |
| 294 | to produce its [timeline CLI][tlc] and [its `/timeline` web view][tlw] |
| 295 | using indexed SQL lookups, which generally have the info you would have |
| 296 | to manually extract from `git log`, produced much more quickly than Git |
| 297 | can, all else being equal: operations over [SQLite’s B-tree data structures][btree] |
| 298 | generally run in O(log n) time, faster than O(n) for equal *n* when the |
| 299 | constants are equal. Yet the constants are *not* equal because Fossil |
| 300 | reads from a single disk file rather than visit potentially many |
| 301 | files in sequence as Git must, so the OS’s buffer cache can result in |
| 302 | [still better performance][35pct]. |
| 303 | |
| 304 | Unlike Git’s log, Fossil’s timeline shows info across branches by |
| 305 | default, a feature for maintaining better situational awareness. The |
| 306 | `fossil timeline` command has no way to show a single branch’s commits, |
| 307 | but you can restrict your view like this using the web UI equivalent by |
| 308 | clicking the name of a branch on the `/timeline` or `/brlist` page. (Or |
| 309 | manually, by adding the `r=` query parameter.) Note that even in this |
| 310 | case, the Fossil timeline still shows other branches where they interact |
| 311 | with the one you’ve referenced in this way; again, better situational |
| 312 | awareness. |
| 313 | |
| 314 | |
| 315 | #### <a id="emu-log"></a> Emulating `git log` |
| 316 | |
| 317 | If you truly need a backwards-in-time-only view of history in Fossil to |
| 318 | emulate `git log`, this is as close as you can currently come: |
| 319 | |
| 320 | fossil timeline parents current |
| 321 | |
| 322 | Again, though, this isn’t restricted to a single branch, as `git log` |
| 323 | is. |
| 324 | |
| 325 | Another useful rough equivalent is: |
| 326 | |
| 327 | git log --raw |
| 328 | fossil time -v |
| 329 | |
| 330 | This shows what changed in each version, though Fossil’s view is more a |
| 331 | summary than a list of raw changes. To dig deeper into single commits, |
| 332 | you can use Fossil’s [`info` command][infoc] or its [`/info` view][infow]. |
| 333 | |
| 334 | Inversely, you may more exactly emulate the default `fossil timeline` |
| 335 | output with `git log --name-status`. |
| 336 | |
| 337 | |
| 338 | #### <a id="whatchanged"></a> What Changed? |
| 339 | |
| 340 | A related — though deprecated — command is `git whatchanged`, which gives results similar to |
| 341 | `git log --raw`, so we cover it here. |
| 342 | |
| 343 | Though there is no `fossil whatchanged` command, the same sort of |
| 344 | information is available. For example, to pull the current changes from |
| 345 | the remote repository and then inspect them before updating the local |
| 346 | working directory, you might say this in Git: |
| 347 | |
| 348 | git fetch |
| 349 | git whatchanged ..@{u} |
| 350 | |
| 351 | …which you can approximate in Fossil as: |
| 352 | |
| 353 | fossil pull |
| 354 | fossil up -n |
| 355 | fossil diff --from tip |
| 356 | |
| 357 | To invert the `diff` to show a more natural patch, the command needs to |
| 358 | be a bit more complicated, since you can’t currently give `--to` |
| 359 | without `--from`. |
| 360 | |
| 361 | fossil diff --from current --to tip |
| 362 | |
| 363 | Rather than use the “dry run” form of [the `update` command][up], you can |
| 364 | say: |
| 365 | |
| 366 | fossil timeline after current |
| 367 | |
| 368 | …or if you want to restrict the output to the current branch: |
| 369 | |
| 370 | fossil timeline descendants current |
| 371 | |
| 372 | |
| 373 | #### <a id="ckin-names"></a> Symbolic Check-In Names |
| 374 | |
| 375 | Note the use of [human-readable symbolic version names][scin] in Fossil |
| 376 | rather than [Git’s cryptic notations][gcn]. |
| 377 | |
| 378 | For a more dramatic example of this, let us ask Git, “What changed since the |
| 379 | beginning of last month?” being October 2020 as I write this: |
| 380 | |
| 381 | git log master@{2020-10-01}..HEAD |
| 382 | |
| 383 | That’s rather obscure! Fossil answers the same question with a simpler |
| 384 | command: |
| 385 | |
| 386 | fossil timeline after 2020-10-01 |
| 387 | |
| 388 | You may need to add `-n 0` to bypass the default output limit of |
| 389 | `fossil timeline`, 20 entries. Without that, this command reads |
| 390 | almost like English. |
| 391 | |
| 392 | Some Git users like to write commands like the above so: |
| 393 | |
| 394 | git log @{2020-10-01}..@ |
| 395 | |
| 396 | Is that better? “@” now means two different things: an at-time reference |
| 397 | and a shortcut for `HEAD`! |
| 398 | |
| 399 | If you are one of those that like short commands, Fossil’s method is |
| 400 | less cryptic: it lets you shorten words in most cases up to the point |
| 401 | that they become ambiguous. For example, you may abbreviate the last |
| 402 | `fossil` command in the prior section: |
| 403 | |
| 404 | fossil tim d c |
| 405 | |
| 406 | …beyond which the `timeline` command becomes ambiguous with `ticket`. |
| 407 | |
| 408 | Some Fossil users employ shell aliases, symlinks, or scripts to shorten |
| 409 | the command still further: |
| 410 | |
| 411 | alias f=fossil |
| 412 | f tim d c |
| 413 | |
| 414 | Granted, that’s rather obscure, but you you can also choose something |
| 415 | intermediate like “`f time desc curr`”, which is reasonably clear. |
| 416 | |
| 417 | [35pct]: https://www.sqlite.org/fasterthanfs.html |
| 418 | [btree]: https://sqlite.org/btreemodule.html |
| 419 | [gcn]: https://git-scm.com/docs/gitrevisions |
| 420 | [infoc]: /help?cmd=info |
| 421 | [infow]: /help?cmd=/info |
| 422 | [ocomp]: https://www.bigocheatsheet.com/ |
| 423 | [tlc]: /help?cmd=timeline |
| 424 | [tlw]: /help?cmd=/timeline |
| 425 | [up]: /help?cmd=update |
| 426 | [wdm]: ./fossil-v-git.wiki#durable |
| 427 | |
| 428 | |
| 429 | ## <a id="dhead"></a> Detached HEAD State |
| 430 | |
| 431 | The SQL indexes in Fossil which we brought up above have a very useful |
| 432 | side benefit: you cannot have a [detached HEAD state][gdh] in Fossil, |
| 433 | the source of untold pain and data loss in Git. It simply cannot be done |
| 434 | in Fossil, because the indexes always let us find our way back into the |
| 435 | hash tree. |
| 436 | |
| 437 | |
| 438 | ## <a id="slcom"></a> Summary Line Convention In Commit Comments |
| 439 | |
| 440 | The Git convention of a [length-limited summary line][lsl] at the start |
| 441 | of commit comments has no equivalent in Fossil. You’re welcome to style |
| 442 | your commit comments thus, but the convention isn’t used or enforced |
| 443 | anywhere in Fossil. For instance, setting `EDITOR=vim` and making a |
| 444 | commit doesn’t do syntax highlighting on the commit message to warn that |
| 445 | you’ve gone over the conventional limit on the first line, and the |
| 446 | Fossil web timeline display doesn’t show the summary line in bold. |
| 447 | |
| 448 | If you wish to follow such conventions in a Fossil project, you may want |
| 449 | to enable the “Allow block-markup in timeline” setting under Admin → |
| 450 | Timeline in the web UI to prevent Fossil from showing the message as a |
| 451 | single paragraph, sans line breaks. [Skin customization][cskin] would |
| 452 | allow you to style the first line of the commit message in bold in |
| 453 | `/timeline` views. |
| 454 | |
| 455 | [cskin]: ./customskin.md |
| 456 | [lsl]: https://chris.beams.io/posts/git-commit/#limit-50 |
| 457 | |
| 458 | |
| 459 | |
| 460 | <a id="staging"></a> |
| 461 | ## There Is No Staging Area |
| 462 | |
| @@ -192,35 +467,40 @@ | |
| 467 | If you only want to commit _some_ of the changes, list the names |
| 468 | of the files or directories you want to commit as arguments, like this: |
| 469 | |
| 470 | fossil commit src/feature.c doc/feature.md examples/feature |
| 471 | |
| 472 | There are currently no interactive patching features in Fossil like |
| 473 | `git add --patch/-p` or `git commit -p`. [Contributions welcome!][ctrb] |
| 474 | |
| 475 | [ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki |
| 476 | |
| 477 | |
| 478 | <a id="bneed"></a> |
| 479 | ## Create Branches At Point Of Need, Rather Than Ahead of Need |
| 480 | |
| 481 | Fossil prefers that you create new branches as part of the first commit |
| 482 | on that branch: |
| 483 | |
| 484 | fossil commit --branch my-new-branch |
| 485 | |
| 486 | If that commit is successful, your local check-out directory is then |
| 487 | switched to the tip of that branch, so subsequent commits don’t need the |
| 488 | “`--branch`” option. You simply say `fossil commit` again to continue |
| 489 | adding commits to the tip of that branch. |
| 490 | |
| 491 | To switch back to the parent branch, say something like: |
| 492 | |
| 493 | fossil update trunk # ≅ git checkout master |
| 494 | |
| 495 | Fossil does also support the Git style, creating the branch ahead of |
| 496 | need: |
| 497 | |
| 498 | fossil branch new my-new-branch |
| 499 | fossil update my-new-branch |
| 500 | ...work on first commit... |
| 501 | fossil commit |
| 502 | |
| 503 | This is more verbose, but it has the same effect: put the first commit |
| 504 | onto `my-new-branch` and switch the check-out directory to that branch so |
| 505 | subsequent commits are descendants of that initial branch commit. |
| 506 | |
| @@ -228,13 +508,14 @@ | |
| 508 | *after* you commit it, using the "`fossil amend`" command. |
| 509 | For example: |
| 510 | |
| 511 | fossil amend current --branch my-new-branch |
| 512 | |
| 513 | (The version string “current” is one of the [special check-in names][scin] in Fossil. See |
| 514 | that document for the many other names you can give to “`amend`”, or |
| 515 | indeed to any other Fossil command documented to accept a `VERSION` or |
| 516 | `NAME` string.) |
| 517 | |
| 518 | [scin]: ./checkin_names.wiki |
| 519 | |
| 520 | |
| 521 | <a id="autosync"></a> |
| @@ -264,11 +545,11 @@ | |
| 545 | 2. It provides immediate off-machine backup of your commits. Unlike |
| 546 | centralized version control, though, you can still work while |
| 547 | disconnected; your changes will sync up with the remote once you get |
| 548 | back online. |
| 549 | |
| 550 | 3. Because there is little distinction between the clones in the Fossil |
| 551 | model — unlike in Git, where clones often quickly diverge from each |
| 552 | other, quite possibly on purpose — the backup advantage applies in inverse |
| 553 | as well: if the remote server falls over dead, one of those with a |
| 554 | clone of that repository can stand it back up, and everyone can get |
| 555 | back to work simply by re-pointing their local repo at the new |
| @@ -285,44 +566,49 @@ | |
| 566 | |
| 567 | <a id="syncall"></a> |
| 568 | ## Sync Is All-Or-Nothing |
| 569 | |
| 570 | Fossil does not support the concept of syncing, pushing, or pulling |
| 571 | individual branches. When you sync/push/pull in Fossil, it |
| 572 | processes all artifacts in its hash tree: |
| 573 | branches, tags, wiki articles, tickets, forum posts, technotes… |
| 574 | This is [not quite “everything,” full stop][bu], but it’s close. |
| 575 | |
| 576 | Furthermore, branch *names* sync automatically in Fossil, not just the |
| 577 | content of those branches. That means this common Git command: |
| 578 | |
| 579 | git push origin master |
| 580 | |
| 581 | …is simply this in Fossil: |
| 582 | |
| 583 | fossil push |
| 584 | |
| 585 | Fossil doesn’t need to be told what to push or where to push it: it just |
| 586 | keeps using the same remote server URL you gave it last |
| 587 | until you [tell it to do something different][rem], and it pushes all |
| 588 | branches, not just one named local branch. |
| 589 | |
| 590 | [rem]: /help?cmd=remote |
| 591 | |
| 592 | |
| 593 | <a id="trunk"></a> |
| 594 | ## The Main Branch Is Called "`trunk`" |
| 595 | |
| 596 | In Fossil, the default name for the main branch |
| 597 | is "`trunk`". The "`trunk`" branch in Fossil corresponds to the |
| 598 | "`master`" branch in stock Git or to [the “`main`” branch in GitHub][mbgh]. |
| 599 | |
| 600 | Because the `fossil git export` command has to work with both stock Git |
| 601 | and with GitHub, Fossil uses Git’s traditional default rather than |
| 602 | GitHub’s new default: your Fossil repo’s “trunk” branch becomes “master” |
| 603 | when [mirroring to GitHub][mirgh], not “main.” |
| 604 | |
| 605 | We do not know what happens on subsequent exports if you later rename |
| 606 | this branch on the GitHub side. |
| 607 | |
| 608 | [mbgh]: https://github.com/github/renaming |
| 609 | [mirgh]: ./mirrortogithub.md |
| 610 | |
| 611 | |
| 612 | <a id="unmanaged"></a> |
| 613 | ## The "`fossil status`" Command Does Not Show Unmanaged Files |
| 614 | |
| @@ -348,30 +634,106 @@ | |
| 634 | come up with a new objection that we haven’t already considered and |
| 635 | addressed there. |
| 636 | |
| 637 | [3]: ./rebaseharm.md |
| 638 | |
| 639 | |
| 640 | ## <a id="show"></a> Showing Information About Commits |
| 641 | |
| 642 | While there is no direct equivalent to Git’s “`show`” command, similar |
| 643 | functionality may be present in Fossil under other commands: |
| 644 | |
| 645 | |
| 646 | #### <a name="patch"></a> Show A Patch For A Commit |
| 647 | |
| 648 | git show -p COMMIT_ID |
| 649 | |
| 650 | …gives much the same output as |
| 651 | |
| 652 | fossil diff --checkin COMMIT_ID |
| 653 | |
| 654 | …only without the patch email header. Git comes out of the [LKML] world, |
| 655 | where emailing a patch is a normal thing to do. Fossil is [designed for |
| 656 | cohesive teams][devorg] where such drive-by patches are rarer. |
| 657 | |
| 658 | You can use any of [Fossil’s special check-in names][scin] in place of |
| 659 | the `COMMIT_ID` in this and later examples. Fossil docs usually say |
| 660 | “`VERSION`” or “`NAME`” where this is allowed, since the version string |
| 661 | or name might not refer to a commit ID, but instead to a forum post, a |
| 662 | wiki document, etc. The following command answers the question “What did |
| 663 | I just commit?” |
| 664 | |
| 665 | fossil diff --checkin tip |
| 666 | |
| 667 | [devorg]: ./fossil-v-git.wiki#devorg |
| 668 | [LKML]: https://lkml.org/ |
| 669 | |
| 670 | |
| 671 | #### <a name="cmsg"></a> Show A Specific Commit Message |
| 672 | |
| 673 | git show -s COMMIT_ID |
| 674 | |
| 675 | |
| 676 | …is |
| 677 | |
| 678 | fossil time -n 1 COMMIT_ID |
| 679 | |
| 680 | …or with a shorter, more obvious command, though with more verbose output: |
| 681 | |
| 682 | fossil info COMMIT_ID |
| 683 | |
| 684 | The `fossil info` command isn’t otherwise a good equivalent to |
| 685 | `git show`; it just overlaps its functionality in some areas. Much of |
| 686 | what’s missing is present in the corresponding [`/info` web |
| 687 | view][infow], though. |
| 688 | |
| 689 | |
| 690 | #### <a name="dstat"></a> Diff Statistics |
| 691 | |
| 692 | Fossil doesn’t have an internal equivalent to commands like |
| 693 | `git show --stat`, but it’s easily remedied by using |
| 694 | [the widely-available `diffstat` tool][dst]: |
| 695 | |
| 696 | fossil diff -i --from 2020-04-01 | diffstat |
| 697 | |
| 698 | We gave the `-i` flag here to force Fossil to use its internal diff |
| 699 | implementation, bypassing [your local `diff-command` setting][dcset]. |
| 700 | If you had that set to [`colordiff`][cdiff], for example, its output |
| 701 | would confuse `diffstat`. |
| 702 | |
| 703 | [cdiff]: https://www.colordiff.org/ |
| 704 | [dcset]: https://fossil-scm.org/home/help?cmd=diff-command |
| 705 | [dst]: https://invisible-island.net/diffstat/diffstat.html |
| 706 | |
| 707 | |
| 708 | <a id="btnames"></a> |
| 709 | ## Branch And Tag Names |
| 710 | |
| 711 | Fossil has no special restrictions on the names of tags and branches, |
| 712 | though you might want to keep [Git's tag and branch name restrictions][gcrf] |
| 713 | in mind if you plan on [mirroring your Fossil repository to GitHub][mirgh]. |
| 714 | |
| 715 | Fossil does not require tag and branch names to be unique. It is |
| 716 | common, for example, to put a "`release`" tag on every release for a |
| 717 | Fossil-hosted project. This does not create a conflict in Fossil, since |
| 718 | Fossil resolves the ambiguity in a predictable way: the newest match |
| 719 | wins. Therefore, “`fossil up release`” always gets you the current |
| 720 | release in a project that uses this tagging convention. |
| 721 | |
| 722 | [The `fossil git export` command][fge] squashes repeated tags down to a |
| 723 | single instance to avoid confusing Git, exporting only the newest tag, |
| 724 | emulating Fossil’s own ambiguity resolution rule as best it can within |
| 725 | Git’s limitations. |
| 726 | |
| 727 | [fge]: /help?cmd=git |
| 728 | [gcrf]: https://git-scm.com/docs/git-check-ref-format |
| 729 | |
| 730 | |
| 731 | |
| 732 | |
| 733 | <a id="cpickrev"></a> |
| 734 | ## Cherry-Picking And Reverting Commits |
| 735 | |
| 736 | Git’s separate "`git cherry-pick`" and “`git revert`” commands are |
| 737 | options to the [`fossil merge` command][merge]: `--cherrypick` and |
| 738 | `--backout`, respectively. |
| 739 | |
| @@ -390,35 +752,175 @@ | |
| 752 | default: they do not actually rename or delete the files in your |
| 753 | check-out. |
| 754 | |
| 755 | If you don’t like that default, you can change it globally: |
| 756 | |
| 757 | fossil setting --global mv-rm-files 1 |
| 758 | |
| 759 | Now these commands behave like in Git in any Fossil repository where |
| 760 | this setting hasn’t been overridden locally. |
| 761 | |
| 762 | If you want to keep Fossil’s soft `mv/rm` behavior most of the time, you |
| 763 | can cast it away on a per-command basis: |
| 764 | |
| 765 | fossil mv --hard old-name new-name |
| 766 | |
| 767 | [mv]: /help?cmd=mv |
| 768 | [rm]: /help?cmd=rm |
| 769 | |
| 770 | |
| 771 | ---- |
| 772 | |
| 773 | |
| 774 | ## <a id="cvdate" name="cs1"></a> Case Study 1: Checking Out A Version By Date |
| 775 | |
| 776 | Let’s get into something a bit more complicated: a case study showing |
| 777 | how the concepts lined out above cause Fossil to materially differ in |
| 778 | day-to-day operation from Git. |
| 779 | |
| 780 | Why would you want to check out a version of a project by date? Perhaps |
| 781 | because your customer gave you a vague bug report referencing only a |
| 782 | date rather than a version. Or, you may be poking semi-randomly through |
| 783 | history to find a “good” version to anchor the start point of a |
| 784 | [`bisect`][bis] operation. |
| 785 | |
| 786 | My search engine’s first result for “git checkout by date” is [this |
| 787 | highly-upvoted accepted Stack Overflow answer][gcod]. The first command |
| 788 | it gives is based on Git’s [`rev-parse` feature][grp]: |
| 789 | |
| 790 | git checkout master@{2020-03-17} |
| 791 | |
| 792 | There are a number of weaknesses in this command. From least to most |
| 793 | critical: |
| 794 | |
| 795 | 1. It’s a bit cryptic. Leave off the refname or punctuation, and it |
| 796 | means something else. You cannot simplify the cryptic incantation in |
| 797 | the typical use case. |
| 798 | |
| 799 | 2. A date string in Git without a time will be interpreted as |
| 800 | “[at localtime on that date][gapxd],” so the command means something |
| 801 | different from one second to the next! If there are multiple commits |
| 802 | on that date, that command can give different results depending on |
| 803 | the time of day you run it. |
| 804 | |
| 805 | 3. It gives misleading output if there is no close match for the date |
| 806 | in target commit in the local [reflog]. On a fresh clone, the reflog |
| 807 | is empty, and even on a well-established clone, Git [automatically |
| 808 | prunes][gle] the reflog to 90 days of history by default. This means |
| 809 | the command above can give different results from one machine to the |
| 810 | next, or even from one day to the next on the same clone. |
| 811 | |
| 812 | The command won’t fail outright if the reflog can’t resolve the |
| 813 | given date: it simply gives the closest commit it can come up with, |
| 814 | even if it’s months or years out from your target! Sometimes it |
| 815 | gives a warning about the reflog not going back far enough to give a |
| 816 | useful result, and sometimes it doesn’t. If you’re on a fresh clone, |
| 817 | you are likely to get the “tip” commit’s revision ID no matter what |
| 818 | date value you give. |
| 819 | |
| 820 | Git tries its best, but because it’s working from a purgeable and |
| 821 | possibly-stale local cache, you cannot trust its results. |
| 822 | |
| 823 | We cannot recommend this command at all. It’s unreliable even in the |
| 824 | best case. |
| 825 | |
| 826 | That same Stack Overflow answer therefore goes on to recommend an |
| 827 | entirely different command: |
| 828 | |
| 829 | git checkout $(git rev-list -n 1 --first-parent --before="2020-03-17" master) |
| 830 | |
| 831 | We believe you get such answers to Git help requests in part |
| 832 | because of its lack of an always-up-to-date [index into its log](#log) and in |
| 833 | part because of its “small tools loosely joined” design philosophy. This |
| 834 | sort of command is therefore composed piece by piece: |
| 835 | |
| 836 | <center>◆ ◆ ◆</center> |
| 837 | |
| 838 | “Oh, I know, I’ll search the rev-list, which outputs commit IDs by |
| 839 | parsing the log backwards from `HEAD`! Easy!” |
| 840 | |
| 841 | git rev-list --before=2020-03-17 |
| 842 | |
| 843 | “Blast! Forgot the commit ID!” |
| 844 | |
| 845 | git rev-list --before=2020-03-17 master |
| 846 | |
| 847 | “Double blast! It just spammed my terminal with revision IDs! I need to |
| 848 | limit it to the single closest match: |
| 849 | |
| 850 | git rev-list -n 1 --before=2020-03-17 master |
| 851 | |
| 852 | “Okay, it gives me a single revision ID now, but is it what I’m after? |
| 853 | Let’s take a look…” |
| 854 | |
| 855 | git show $(git rev-list -n 1 --before=2020-03-17 master) |
| 856 | |
| 857 | “Oops, that’s giving me a merge commit, not what I want. |
| 858 | Off to search the web… Okay, it says I need to give either the |
| 859 | `--first-parent` or `--no-merges` flag to show only regular commits, |
| 860 | not merge-commits. Let’s try the first one:” |
| 861 | |
| 862 | git show $(git rev-list -n 1 --first-parent --before=2020-03-17 master) |
| 863 | |
| 864 | “Better. Let’s check it out:” |
| 865 | |
| 866 | git checkout $(git rev-list -n 1 --first-parent --before=2020-03-17 master) |
| 867 | |
| 868 | “Success, I guess?” |
| 869 | |
| 870 | <center>◆ ◆ ◆</center> |
| 871 | |
| 872 | This vignette is meant to explain some of Git’s popularity: it rewards |
| 873 | the sort of people who enjoy puzzles, many of whom are software |
| 874 | developers and thus need a tool like Git. Too bad if you’re just a |
| 875 | normal user. |
| 876 | |
| 877 | And too bad if you’re a Windows user who doesn’t want to use [Git |
| 878 | Bash][gbash], since neither of the stock OS command shells have a |
| 879 | command interpolation feature needed to run that horrid command. |
| 880 | |
| 881 | This alternative command still has weakness #2 above: if you run the |
| 882 | second `git show` command above on [Git’s own repository][gitgh], your |
| 883 | results may vary because there were four non-merge commits to Git on the |
| 884 | 17th of March, 2020. |
| 885 | |
| 886 | You may be asking with an exasperated huff, “What is your *point*, man?” |
| 887 | The point is that the equivalent in Fossil is simply: |
| 888 | |
| 889 | fossil up 2020-03-17 |
| 890 | |
| 891 | …which will *always* give the commit closest to midnight UTC on the 17th |
| 892 | of March, 2020, no matter whether you do it on a fresh clone or a stale |
| 893 | one. The answer won’t shift about from one clone to the next or from |
| 894 | one local time of day to the next. We owe this reliability and stability |
| 895 | to three Fossil design choices: |
| 896 | |
| 897 | * Parse timestamps from all commits on clone into a local commit index, |
| 898 | then maintain that index through subsequent commits and syncs. |
| 899 | |
| 900 | * Use an indexed SQL `ORDER BY` query to match timestamps to commit |
| 901 | IDs for a fast and consistent result. |
| 902 | |
| 903 | * Round timestamp strings up using [rules][frud] consistent across |
| 904 | computers and local time of day. |
| 905 | |
| 906 | [frud]: https://fossil-scm.org/home/file/src/name.c?ci=d2a59b03727bc3&ln=122-141 |
| 907 | [gbash]: https://appuals.com/what-is-git-bash/ |
| 908 | [gapxd]: https://github.com/git/git/blob/7f7ebe054a/date.c#L1298-L1300 |
| 909 | [gcod]: https://stackoverflow.com/a/6990682/142454 |
| 910 | [gdh]: https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit/ |
| 911 | [gitgh]: https://github.com/git/git/ |
| 912 | [gle]: https://git-scm.com/docs/git-reflog#_options_for_expire |
| 913 | [gmc]: https://github.com/git/git/commit/67b0a24910fbb23c8f5e7a2c61c339818bc68296 |
| 914 | [grp]: https://git-scm.com/docs/git-rev-parse |
| 915 | [reflog]: https://git-scm.com/docs/git-reflog |
| 916 | |
| 917 | ---- |
| 918 | |
| 919 | ## <a id="morigin" name="cs2"></a> Case Study 2: Multiple "origin" Servers |
| 920 | |
| 921 | Now let us consider a common use case at the time of this writing — during the |
| 922 | COVID-19 pandemic — where you’re working from home a lot, going into the |
| 923 | office one part-day a week only to do things that have to be done |
| 924 | on-site at the office. Let us also say you have no remote |
| 925 | access back into the work LAN, such as because your site IT is paranoid |
| 926 | about security. You may still want off-machine backups of your commits |
| @@ -448,20 +950,20 @@ | |
| 950 | |
| 951 | ssh my-nas.local 'git init --bare /SHARES/dayjob/repo.git' |
| 952 | git push --all ssh://my-nas.local//SHARES/dayjob/repo.git |
| 953 | |
| 954 | Realize that this is carefully optimized down to these two long |
| 955 | commands. In practice, we’d expect a user typing these commands by hand from memory |
| 956 | to need to give four or more commands here instead. |
| 957 | Packing the “`git init`” call into the “`ssh`” call is something more |
| 958 | often done in scripts and documentation examples than done interactively, |
| 959 | which then necessitates a third command before the push, “`exit`”. |
| 960 | There’s also a good chance that you’ll forget the need for the `--bare` |
| 961 | option here to avoid a fatal complaint from Git that the laptop can’t |
| 962 | push into a non-empty repo. If you fall into this trap, among the many |
| 963 | that Git lays for newbies, you have to nuke the incorrectly initted |
| 964 | repo, search the web or Git man pages to find out about `--bare`, and try again. |
| 965 | |
| 966 | Having navigated that little minefield, |
| 967 | we can tell Git that there is a second origin, a “home” repo in |
| 968 | addition to the named “work” repo we set up earlier: |
| 969 | |
| @@ -469,11 +971,11 @@ | |
| 971 | git config master.remote home |
| 972 | |
| 973 | We don’t have to push or pull because the remote repo is a complete |
| 974 | clone of the repo on the laptop at this point, so we can just get to |
| 975 | work now, committing along the way to get our work safely off-machine |
| 976 | and onto our home NAS, like so: |
| 977 | |
| 978 | git add |
| 979 | git commit |
| 980 | git push |
| 981 | |
| @@ -493,38 +995,38 @@ | |
| 995 | that when returning home, you’d have to manually reset the upstream |
| 996 | again. |
| 997 | |
| 998 | This example also shows a consequence of that fact that |
| 999 | [Git doesn’t sync branch names](#syncall): you have to keep repeating |
| 1000 | yourself like an obsequious supplicant: “Master, master.” Didn’t we |
| 1001 | invent computers to serve humans, rather than the other way around? |
| 1002 | |
| 1003 | |
| 1004 | #### Fossil Method |
| 1005 | |
| 1006 | Now we’re going to do the same thing using Fossil, with |
| 1007 | the commands arranged in blocks corresponding to those above for comparison. |
| 1008 | |
| 1009 | We start the same way, cloning the work repo down to the laptop: |
| 1010 | |
| 1011 | fossil clone https://dev-server.example.com/repo |
| 1012 | cd repo |
| 1013 | fossil remote add work https://dev-server.example.com/repo |
| 1014 | |
| 1015 | We’ve chosen the new “`fossil clone URI`” syntax added in Fossil 2.14 rather than separate |
| 1016 | `clone` and `open` commands to make the parallel with Git clearer. [See |
| 1017 | above](#mwd) for more on that topic. |
| 1018 | |
| 1019 | Our [`remote` command][rem] is longer than the Git equivalent because |
| 1020 | Fossil currently has no short command |
| 1021 | to rename an existing remote. Worse, unlike with Git, we can’t just keep |
| 1022 | using the default remote name because Fossil uses that slot in its |
| 1023 | configuration database to store the *current* remote name, so on |
| 1024 | switching from work to home, the home URL will overwrite the work URL if |
| 1025 | we don’t give it an explicit name first. |
| 1026 | |
| 1027 | Although the Fossil commands are longer, so far, keep it in perspective: |
| 1028 | they’re one-time setup costs, |
| 1029 | easily amortized to insignificance by the shorter day-to-day commands |
| 1030 | below. |
| 1031 | |
| 1032 | On first beginning to work from home, we reverse-clone the Fossil repo |
| 1033 |
+4
-4
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -84,16 +84,16 @@ | ||
| 84 | 84 | the repository are consistent prior to each commit. |
| 85 | 85 | |
| 86 | 86 | 8. <b>Free and Open-Source</b> - Uses the [../COPYRIGHT-BSD2.txt|2-clause BSD license]. |
| 87 | 87 | |
| 88 | 88 | <hr> |
| 89 | -<h3>Latest Release: 2.12.1 ([/timeline?c=202008201327|2020-08-20])</h3> | |
| 89 | +<h3>Latest Release: 2.13 ([/timeline?c=version-2.13|2020-11-01])</h3> | |
| 90 | 90 | |
| 91 | 91 | * [/uv/download.html|Download] |
| 92 | - * [./changes.wiki#v2_12|Change Summary] | |
| 93 | - * [/timeline?p=version-2.12.1&bt=version-2.11&n=all|Check-ins in version 2.12.1] | |
| 94 | - * [/timeline?d=version-2.12&n=all&nd|Check-ins derived from the 2.12 release] | |
| 92 | + * [./changes.wiki#v2_13|Change Summary] | |
| 93 | + * [/timeline?p=version-2.13&bt=version-2.12&n=all|Check-ins in version 2.13] | |
| 94 | + * [/timeline?d=version-2.13&n=all&nd|Check-ins derived from the 2.13 release] | |
| 95 | 95 | * [/timeline?t=release|Timeline of all past releases] |
| 96 | 96 | |
| 97 | 97 | <hr> |
| 98 | 98 | <h3>Quick Start</h3> |
| 99 | 99 | |
| 100 | 100 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -84,16 +84,16 @@ | |
| 84 | the repository are consistent prior to each commit. |
| 85 | |
| 86 | 8. <b>Free and Open-Source</b> - Uses the [../COPYRIGHT-BSD2.txt|2-clause BSD license]. |
| 87 | |
| 88 | <hr> |
| 89 | <h3>Latest Release: 2.12.1 ([/timeline?c=202008201327|2020-08-20])</h3> |
| 90 | |
| 91 | * [/uv/download.html|Download] |
| 92 | * [./changes.wiki#v2_12|Change Summary] |
| 93 | * [/timeline?p=version-2.12.1&bt=version-2.11&n=all|Check-ins in version 2.12.1] |
| 94 | * [/timeline?d=version-2.12&n=all&nd|Check-ins derived from the 2.12 release] |
| 95 | * [/timeline?t=release|Timeline of all past releases] |
| 96 | |
| 97 | <hr> |
| 98 | <h3>Quick Start</h3> |
| 99 | |
| 100 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -84,16 +84,16 @@ | |
| 84 | the repository are consistent prior to each commit. |
| 85 | |
| 86 | 8. <b>Free and Open-Source</b> - Uses the [../COPYRIGHT-BSD2.txt|2-clause BSD license]. |
| 87 | |
| 88 | <hr> |
| 89 | <h3>Latest Release: 2.13 ([/timeline?c=version-2.13|2020-11-01])</h3> |
| 90 | |
| 91 | * [/uv/download.html|Download] |
| 92 | * [./changes.wiki#v2_13|Change Summary] |
| 93 | * [/timeline?p=version-2.13&bt=version-2.12&n=all|Check-ins in version 2.13] |
| 94 | * [/timeline?d=version-2.13&n=all&nd|Check-ins derived from the 2.13 release] |
| 95 | * [/timeline?t=release|Timeline of all past releases] |
| 96 | |
| 97 | <hr> |
| 98 | <h3>Quick Start</h3> |
| 99 | |
| 100 |
+10
-1
| --- www/mirrortogithub.md | ||
| +++ www/mirrortogithub.md | ||
| @@ -77,14 +77,23 @@ | ||
| 77 | 77 | <pre>$ fossil git status</pre> |
| 78 | 78 | </blockquote> |
| 79 | 79 | </ol> |
| 80 | 80 | |
| 81 | 81 | ## Notes: |
| 82 | + | |
| 83 | + * Unless you specify --force, the mirroring only happens if the Fossil | |
| 84 | + repo has changed, with Fossil reporting "no changes", because Fossil | |
| 85 | + does not care about the success or failure of the mirror run. If a mirror | |
| 86 | + run failed (for example, due to an incorrect password, or a transient | |
| 87 | + error at github.com), Fossil will not retry until there has been a repo | |
| 88 | + change or --force is supplied. | |
| 82 | 89 | |
| 83 | 90 | * The mirroring is one-way. If you check in changes on GitHub, those |
| 84 | 91 | changes will not be reabsorbed by Fossil. There are technical problems |
| 85 | - that make a two-way mirror all but impossible. | |
| 92 | + that make a two-way mirror all but impossible. (This is not to be | |
| 93 | + confused with the ability to import a Fossil mirror from Github back | |
| 94 | + into a Fossil repository. That works, but it is not a mirror.) | |
| 86 | 95 | |
| 87 | 96 | This also means that you cannot accept pull requests on GitHub. |
| 88 | 97 | |
| 89 | 98 | * The "`fossil git export`" command creates subprocesses that run "`git`" |
| 90 | 99 | commands, so you must have Git installed on your machine for any |
| 91 | 100 |
| --- www/mirrortogithub.md | |
| +++ www/mirrortogithub.md | |
| @@ -77,14 +77,23 @@ | |
| 77 | <pre>$ fossil git status</pre> |
| 78 | </blockquote> |
| 79 | </ol> |
| 80 | |
| 81 | ## Notes: |
| 82 | |
| 83 | * The mirroring is one-way. If you check in changes on GitHub, those |
| 84 | changes will not be reabsorbed by Fossil. There are technical problems |
| 85 | that make a two-way mirror all but impossible. |
| 86 | |
| 87 | This also means that you cannot accept pull requests on GitHub. |
| 88 | |
| 89 | * The "`fossil git export`" command creates subprocesses that run "`git`" |
| 90 | commands, so you must have Git installed on your machine for any |
| 91 |
| --- www/mirrortogithub.md | |
| +++ www/mirrortogithub.md | |
| @@ -77,14 +77,23 @@ | |
| 77 | <pre>$ fossil git status</pre> |
| 78 | </blockquote> |
| 79 | </ol> |
| 80 | |
| 81 | ## Notes: |
| 82 | |
| 83 | * Unless you specify --force, the mirroring only happens if the Fossil |
| 84 | repo has changed, with Fossil reporting "no changes", because Fossil |
| 85 | does not care about the success or failure of the mirror run. If a mirror |
| 86 | run failed (for example, due to an incorrect password, or a transient |
| 87 | error at github.com), Fossil will not retry until there has been a repo |
| 88 | change or --force is supplied. |
| 89 | |
| 90 | * The mirroring is one-way. If you check in changes on GitHub, those |
| 91 | changes will not be reabsorbed by Fossil. There are technical problems |
| 92 | that make a two-way mirror all but impossible. (This is not to be |
| 93 | confused with the ability to import a Fossil mirror from Github back |
| 94 | into a Fossil repository. That works, but it is not a mirror.) |
| 95 | |
| 96 | This also means that you cannot accept pull requests on GitHub. |
| 97 | |
| 98 | * The "`fossil git export`" command creates subprocesses that run "`git`" |
| 99 | commands, so you must have Git installed on your machine for any |
| 100 |
+2
-1
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -27,10 +27,11 @@ | ||
| 27 | 27 | cgi.wiki {CGI Script Configuration Options} |
| 28 | 28 | changes.wiki {Fossil Changelog} |
| 29 | 29 | checkin_names.wiki {Check-in And Version Names} |
| 30 | 30 | checkin.wiki {Check-in Checklist} |
| 31 | 31 | childprojects.wiki {Child Projects} |
| 32 | + ckout-workflows.md {Check-Out Workflows} | |
| 32 | 33 | copyright-release.html {Contributor License Agreement} |
| 33 | 34 | concepts.wiki {Fossil Core Concepts} |
| 34 | 35 | contribute.wiki {Contributing Code or Documentation To The Fossil Project} |
| 35 | 36 | css-tricks.md {Fossil CSS Tips and Tricks} |
| 36 | 37 | customgraph.md {Theming: Customizing the Timeline Graph} |
| @@ -52,11 +53,11 @@ | ||
| 52 | 53 | foss-cklist.wiki {Checklist For Successful Open-Source Projects} |
| 53 | 54 | fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} |
| 54 | 55 | fossil_prompt.wiki {Fossilized Bash Prompt} |
| 55 | 56 | fossil-v-git.wiki {Fossil Versus Git} |
| 56 | 57 | globs.md {File Name Glob Patterns} |
| 57 | - gitusers.md {Hints For Users With Git Experience} | |
| 58 | + gitusers.md {Git to Fossil Translation Guide} | |
| 58 | 59 | grep.md {Fossil grep vs POSIX grep} |
| 59 | 60 | hacker-howto.wiki {Hacker How-To} |
| 60 | 61 | hacker-howto.wiki {Fossil Developers Guide} |
| 61 | 62 | hashes.md {Hashes: Fossil Artifact Identification} |
| 62 | 63 | hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} |
| 63 | 64 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -27,10 +27,11 @@ | |
| 27 | cgi.wiki {CGI Script Configuration Options} |
| 28 | changes.wiki {Fossil Changelog} |
| 29 | checkin_names.wiki {Check-in And Version Names} |
| 30 | checkin.wiki {Check-in Checklist} |
| 31 | childprojects.wiki {Child Projects} |
| 32 | copyright-release.html {Contributor License Agreement} |
| 33 | concepts.wiki {Fossil Core Concepts} |
| 34 | contribute.wiki {Contributing Code or Documentation To The Fossil Project} |
| 35 | css-tricks.md {Fossil CSS Tips and Tricks} |
| 36 | customgraph.md {Theming: Customizing the Timeline Graph} |
| @@ -52,11 +53,11 @@ | |
| 52 | foss-cklist.wiki {Checklist For Successful Open-Source Projects} |
| 53 | fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} |
| 54 | fossil_prompt.wiki {Fossilized Bash Prompt} |
| 55 | fossil-v-git.wiki {Fossil Versus Git} |
| 56 | globs.md {File Name Glob Patterns} |
| 57 | gitusers.md {Hints For Users With Git Experience} |
| 58 | grep.md {Fossil grep vs POSIX grep} |
| 59 | hacker-howto.wiki {Hacker How-To} |
| 60 | hacker-howto.wiki {Fossil Developers Guide} |
| 61 | hashes.md {Hashes: Fossil Artifact Identification} |
| 62 | hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} |
| 63 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -27,10 +27,11 @@ | |
| 27 | cgi.wiki {CGI Script Configuration Options} |
| 28 | changes.wiki {Fossil Changelog} |
| 29 | checkin_names.wiki {Check-in And Version Names} |
| 30 | checkin.wiki {Check-in Checklist} |
| 31 | childprojects.wiki {Child Projects} |
| 32 | ckout-workflows.md {Check-Out Workflows} |
| 33 | copyright-release.html {Contributor License Agreement} |
| 34 | concepts.wiki {Fossil Core Concepts} |
| 35 | contribute.wiki {Contributing Code or Documentation To The Fossil Project} |
| 36 | css-tricks.md {Fossil CSS Tips and Tricks} |
| 37 | customgraph.md {Theming: Customizing the Timeline Graph} |
| @@ -52,11 +53,11 @@ | |
| 53 | foss-cklist.wiki {Checklist For Successful Open-Source Projects} |
| 54 | fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE} |
| 55 | fossil_prompt.wiki {Fossilized Bash Prompt} |
| 56 | fossil-v-git.wiki {Fossil Versus Git} |
| 57 | globs.md {File Name Glob Patterns} |
| 58 | gitusers.md {Git to Fossil Translation Guide} |
| 59 | grep.md {Fossil grep vs POSIX grep} |
| 60 | hacker-howto.wiki {Hacker How-To} |
| 61 | hacker-howto.wiki {Fossil Developers Guide} |
| 62 | hashes.md {Hashes: Fossil Artifact Identification} |
| 63 | hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256} |
| 64 |
+5
-4
| --- www/permutedindex.html | ||
| +++ www/permutedindex.html | ||
| @@ -57,10 +57,11 @@ | ||
| 57 | 57 | <li><a href="serverext.wiki"><b>CGI Server Extensions</b></a></li> |
| 58 | 58 | <li><a href="aboutcgi.wiki">CGI Works In Fossil — How</a></li> |
| 59 | 59 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 60 | 60 | <li><a href="checkin_names.wiki"><b>Check-in And Version Names</b></a></li> |
| 61 | 61 | <li><a href="checkin.wiki"><b>Check-in Checklist</b></a></li> |
| 62 | +<li><a href="ckout-workflows.md"><b>Check-Out Workflows</b></a></li> | |
| 62 | 63 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 63 | 64 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 64 | 65 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 65 | 66 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 66 | 67 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| @@ -108,11 +109,10 @@ | ||
| 108 | 109 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 109 | 110 | <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> |
| 110 | 111 | <li><a href="env-opts.md"><b>Environment Variables and Global Options</b></a></li> |
| 111 | 112 | <li><a href="event.wiki"><b>Events</b></a></li> |
| 112 | 113 | <li><a href="webpage-ex.md">Examples — Webpage</a></li> |
| 113 | -<li><a href="gitusers.md">Experience — Hints For Users With Git</a></li> | |
| 114 | 114 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 115 | 115 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 116 | 116 | <li><a href="serverext.wiki">Extensions — CGI Server</a></li> |
| 117 | 117 | <li><a href="serverext.wiki">Extensions To A Fossil Server Using CGI Scripts — Adding</a></li> |
| 118 | 118 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| @@ -147,29 +147,29 @@ | ||
| 147 | 147 | <li><a href="fossil_prompt.wiki"><b>Fossilized Bash Prompt</b></a></li> |
| 148 | 148 | <li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li> |
| 149 | 149 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 150 | 150 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 151 | 151 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 152 | -<li><a href="gitusers.md">Git Experience — Hints For Users With</a></li> | |
| 153 | 152 | <li><a href="mirrorlimitations.md">Git Mirrors — Limitations On</a></li> |
| 153 | +<li><a href="gitusers.md"><b>Git to Fossil Translation Guide</b></a></li> | |
| 154 | 154 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 155 | 155 | <li><a href="mirrortogithub.md">GitHub — How To Mirror A Fossil Repository On</a></li> |
| 156 | 156 | <li><a href="globs.md">Glob Patterns — File Name</a></li> |
| 157 | 157 | <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> |
| 158 | 158 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 159 | 159 | <li><a href="grep.md">grep — Fossil grep vs POSIX</a></li> |
| 160 | 160 | <li><a href="grep.md">grep vs POSIX grep — Fossil</a></li> |
| 161 | 161 | <li><a href="hacker-howto.wiki">Guide — Fossil Developers</a></li> |
| 162 | 162 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 163 | +<li><a href="gitusers.md">Guide — Git to Fossil Translation</a></li> | |
| 163 | 164 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 164 | 165 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 165 | 166 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 166 | 167 | <li><a href="rebaseharm.md">Harmful — Rebase Considered</a></li> |
| 167 | 168 | <li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li> |
| 168 | 169 | <li><a href="hashes.md"><b>Hashes: Fossil Artifact Identification</b></a></li> |
| 169 | 170 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 170 | -<li><a href="gitusers.md"><b>Hints For Users With Git Experience</b></a></li> | |
| 171 | 171 | <li><a href="history.md">History Of Fossil — The Purpose And</a></li> |
| 172 | 172 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 173 | 173 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 174 | 174 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 175 | 175 | <li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li> |
| @@ -310,10 +310,11 @@ | ||
| 310 | 310 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 311 | 311 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 312 | 312 | <li><a href="css-tricks.md">Tips and Tricks — Fossil CSS</a></li> |
| 313 | 313 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 314 | 314 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 315 | +<li><a href="gitusers.md">Translation Guide — Git to Fossil</a></li> | |
| 315 | 316 | <li><a href="css-tricks.md">Tricks — Fossil CSS Tips and</a></li> |
| 316 | 317 | <li><a href="unvers.wiki"><b>Unversioned Files</b></a></li> |
| 317 | 318 | <li><a href="backup.md">Up a Remote Fossil Repository — Backing</a></li> |
| 318 | 319 | <li><a href="fiveminutes.wiki"><b>Up and Running in 5 Minutes as a Single User</b></a></li> |
| 319 | 320 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| @@ -320,11 +321,10 @@ | ||
| 320 | 321 | <li><a href="javascript.md"><b>Use of JavaScript in Fossil</b></a></li> |
| 321 | 322 | <li><a href="fiveminutes.wiki">User — Up and Running in 5 Minutes as a Single</a></li> |
| 322 | 323 | <li><a href="caps/">User Capabilities — Administering</a></li> |
| 323 | 324 | <li><a href="caps/ref.html"><b>User Capability Reference</b></a></li> |
| 324 | 325 | <li><a href="caps/admin-v-setup.md">Users — Differences Between Setup and Admin</a></li> |
| 325 | -<li><a href="gitusers.md">Users With Git Experience — Hints For</a></li> | |
| 326 | 326 | <li><a href="serverext.wiki">Using CGI Scripts — Adding Extensions To A Fossil Server</a></li> |
| 327 | 327 | <li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li> |
| 328 | 328 | <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> |
| 329 | 329 | <li><a href="whyusefossil.wiki">Version Control — Benefits Of</a></li> |
| 330 | 330 | <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> |
| @@ -338,9 +338,10 @@ | ||
| 338 | 338 | <li><a href="../../../help">Webpages — Lists of Commands and</a></li> |
| 339 | 339 | <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> |
| 340 | 340 | <li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li> |
| 341 | 341 | <li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li> |
| 342 | 342 | <li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li> |
| 343 | +<li><a href="ckout-workflows.md">Workflows — Check-Out</a></li> | |
| 343 | 344 | <li><a href="aboutdownload.wiki">Works — How The Download Page</a></li> |
| 344 | 345 | <li><a href="aboutcgi.wiki">Works In Fossil — How CGI</a></li> |
| 345 | 346 | <li><a href="whyusefossil.wiki">You Should Use Fossil — Why</a></li> |
| 346 | 347 | </ul></div> |
| 347 | 348 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -57,10 +57,11 @@ | |
| 57 | <li><a href="serverext.wiki"><b>CGI Server Extensions</b></a></li> |
| 58 | <li><a href="aboutcgi.wiki">CGI Works In Fossil — How</a></li> |
| 59 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 60 | <li><a href="checkin_names.wiki"><b>Check-in And Version Names</b></a></li> |
| 61 | <li><a href="checkin.wiki"><b>Check-in Checklist</b></a></li> |
| 62 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 63 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 64 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 65 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 66 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| @@ -108,11 +109,10 @@ | |
| 108 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 109 | <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> |
| 110 | <li><a href="env-opts.md"><b>Environment Variables and Global Options</b></a></li> |
| 111 | <li><a href="event.wiki"><b>Events</b></a></li> |
| 112 | <li><a href="webpage-ex.md">Examples — Webpage</a></li> |
| 113 | <li><a href="gitusers.md">Experience — Hints For Users With Git</a></li> |
| 114 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 115 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 116 | <li><a href="serverext.wiki">Extensions — CGI Server</a></li> |
| 117 | <li><a href="serverext.wiki">Extensions To A Fossil Server Using CGI Scripts — Adding</a></li> |
| 118 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| @@ -147,29 +147,29 @@ | |
| 147 | <li><a href="fossil_prompt.wiki"><b>Fossilized Bash Prompt</b></a></li> |
| 148 | <li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li> |
| 149 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 150 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 151 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 152 | <li><a href="gitusers.md">Git Experience — Hints For Users With</a></li> |
| 153 | <li><a href="mirrorlimitations.md">Git Mirrors — Limitations On</a></li> |
| 154 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 155 | <li><a href="mirrortogithub.md">GitHub — How To Mirror A Fossil Repository On</a></li> |
| 156 | <li><a href="globs.md">Glob Patterns — File Name</a></li> |
| 157 | <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> |
| 158 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 159 | <li><a href="grep.md">grep — Fossil grep vs POSIX</a></li> |
| 160 | <li><a href="grep.md">grep vs POSIX grep — Fossil</a></li> |
| 161 | <li><a href="hacker-howto.wiki">Guide — Fossil Developers</a></li> |
| 162 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 163 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 164 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 165 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 166 | <li><a href="rebaseharm.md">Harmful — Rebase Considered</a></li> |
| 167 | <li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li> |
| 168 | <li><a href="hashes.md"><b>Hashes: Fossil Artifact Identification</b></a></li> |
| 169 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 170 | <li><a href="gitusers.md"><b>Hints For Users With Git Experience</b></a></li> |
| 171 | <li><a href="history.md">History Of Fossil — The Purpose And</a></li> |
| 172 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 173 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 174 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 175 | <li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li> |
| @@ -310,10 +310,11 @@ | |
| 310 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 311 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 312 | <li><a href="css-tricks.md">Tips and Tricks — Fossil CSS</a></li> |
| 313 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 314 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 315 | <li><a href="css-tricks.md">Tricks — Fossil CSS Tips and</a></li> |
| 316 | <li><a href="unvers.wiki"><b>Unversioned Files</b></a></li> |
| 317 | <li><a href="backup.md">Up a Remote Fossil Repository — Backing</a></li> |
| 318 | <li><a href="fiveminutes.wiki"><b>Up and Running in 5 Minutes as a Single User</b></a></li> |
| 319 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| @@ -320,11 +321,10 @@ | |
| 320 | <li><a href="javascript.md"><b>Use of JavaScript in Fossil</b></a></li> |
| 321 | <li><a href="fiveminutes.wiki">User — Up and Running in 5 Minutes as a Single</a></li> |
| 322 | <li><a href="caps/">User Capabilities — Administering</a></li> |
| 323 | <li><a href="caps/ref.html"><b>User Capability Reference</b></a></li> |
| 324 | <li><a href="caps/admin-v-setup.md">Users — Differences Between Setup and Admin</a></li> |
| 325 | <li><a href="gitusers.md">Users With Git Experience — Hints For</a></li> |
| 326 | <li><a href="serverext.wiki">Using CGI Scripts — Adding Extensions To A Fossil Server</a></li> |
| 327 | <li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li> |
| 328 | <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> |
| 329 | <li><a href="whyusefossil.wiki">Version Control — Benefits Of</a></li> |
| 330 | <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> |
| @@ -338,9 +338,10 @@ | |
| 338 | <li><a href="../../../help">Webpages — Lists of Commands and</a></li> |
| 339 | <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> |
| 340 | <li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li> |
| 341 | <li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li> |
| 342 | <li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li> |
| 343 | <li><a href="aboutdownload.wiki">Works — How The Download Page</a></li> |
| 344 | <li><a href="aboutcgi.wiki">Works In Fossil — How CGI</a></li> |
| 345 | <li><a href="whyusefossil.wiki">You Should Use Fossil — Why</a></li> |
| 346 | </ul></div> |
| 347 |
| --- www/permutedindex.html | |
| +++ www/permutedindex.html | |
| @@ -57,10 +57,11 @@ | |
| 57 | <li><a href="serverext.wiki"><b>CGI Server Extensions</b></a></li> |
| 58 | <li><a href="aboutcgi.wiki">CGI Works In Fossil — How</a></li> |
| 59 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 60 | <li><a href="checkin_names.wiki"><b>Check-in And Version Names</b></a></li> |
| 61 | <li><a href="checkin.wiki"><b>Check-in Checklist</b></a></li> |
| 62 | <li><a href="ckout-workflows.md"><b>Check-Out Workflows</b></a></li> |
| 63 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 64 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 65 | <li><a href="foss-cklist.wiki"><b>Checklist For Successful Open-Source Projects</b></a></li> |
| 66 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 67 | <li><a href="childprojects.wiki"><b>Child Projects</b></a></li> |
| @@ -108,11 +109,10 @@ | |
| 109 | <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> |
| 110 | <li><a href="encryptedrepos.wiki">Encrypted Repositories — How To Use</a></li> |
| 111 | <li><a href="env-opts.md"><b>Environment Variables and Global Options</b></a></li> |
| 112 | <li><a href="event.wiki"><b>Events</b></a></li> |
| 113 | <li><a href="webpage-ex.md">Examples — Webpage</a></li> |
| 114 | <li><a href="inout.wiki">Export To And From Git — Import And</a></li> |
| 115 | <li><a href="fossil-from-msvc.wiki">Express 2010 IDE — Integrating Fossil in the Microsoft</a></li> |
| 116 | <li><a href="serverext.wiki">Extensions — CGI Server</a></li> |
| 117 | <li><a href="serverext.wiki">Extensions To A Fossil Server Using CGI Scripts — Adding</a></li> |
| 118 | <li><a href="adding_code.wiki">Features To Fossil — Adding New</a></li> |
| @@ -147,29 +147,29 @@ | |
| 147 | <li><a href="fossil_prompt.wiki"><b>Fossilized Bash Prompt</b></a></li> |
| 148 | <li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li> |
| 149 | <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> |
| 150 | <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> |
| 151 | <li><a href="inout.wiki">Git — Import And Export To And From</a></li> |
| 152 | <li><a href="mirrorlimitations.md">Git Mirrors — Limitations On</a></li> |
| 153 | <li><a href="gitusers.md"><b>Git to Fossil Translation Guide</b></a></li> |
| 154 | <li><a href="quotes.wiki">Git, and DVCSes in General — Quotes: What People Are Saying About Fossil,</a></li> |
| 155 | <li><a href="mirrortogithub.md">GitHub — How To Mirror A Fossil Repository On</a></li> |
| 156 | <li><a href="globs.md">Glob Patterns — File Name</a></li> |
| 157 | <li><a href="env-opts.md">Global Options — Environment Variables and</a></li> |
| 158 | <li><a href="customgraph.md">Graph — Theming: Customizing the Timeline</a></li> |
| 159 | <li><a href="grep.md">grep — Fossil grep vs POSIX</a></li> |
| 160 | <li><a href="grep.md">grep vs POSIX grep — Fossil</a></li> |
| 161 | <li><a href="hacker-howto.wiki">Guide — Fossil Developers</a></li> |
| 162 | <li><a href="quickstart.wiki">Guide — Fossil Quick Start</a></li> |
| 163 | <li><a href="gitusers.md">Guide — Git to Fossil Translation</a></li> |
| 164 | <li><a href="style.wiki">Guidelines — Source Code Style</a></li> |
| 165 | <li><a href="hacker-howto.wiki"><b>Hacker How-To</b></a></li> |
| 166 | <li><a href="adding_code.wiki"><b>Hacking Fossil</b></a></li> |
| 167 | <li><a href="rebaseharm.md">Harmful — Rebase Considered</a></li> |
| 168 | <li><a href="hashpolicy.wiki"><b>Hash Policy: Choosing Between SHA1 and SHA3-256</b></a></li> |
| 169 | <li><a href="hashes.md"><b>Hashes: Fossil Artifact Identification</b></a></li> |
| 170 | <li><a href="hints.wiki">Hints — Fossil Tips And Usage</a></li> |
| 171 | <li><a href="history.md">History Of Fossil — The Purpose And</a></li> |
| 172 | <li><a href="index.wiki"><b>Home Page</b></a></li> |
| 173 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 174 | <li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li> |
| 175 | <li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li> |
| @@ -310,10 +310,11 @@ | |
| 310 | <li><a href="tickets.wiki">Ticket System — The Fossil</a></li> |
| 311 | <li><a href="customgraph.md">Timeline Graph — Theming: Customizing the</a></li> |
| 312 | <li><a href="css-tricks.md">Tips and Tricks — Fossil CSS</a></li> |
| 313 | <li><a href="hints.wiki">Tips And Usage Hints — Fossil</a></li> |
| 314 | <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> |
| 315 | <li><a href="gitusers.md">Translation Guide — Git to Fossil</a></li> |
| 316 | <li><a href="css-tricks.md">Tricks — Fossil CSS Tips and</a></li> |
| 317 | <li><a href="unvers.wiki"><b>Unversioned Files</b></a></li> |
| 318 | <li><a href="backup.md">Up a Remote Fossil Repository — Backing</a></li> |
| 319 | <li><a href="fiveminutes.wiki"><b>Up and Running in 5 Minutes as a Single User</b></a></li> |
| 320 | <li><a href="hints.wiki">Usage Hints — Fossil Tips And</a></li> |
| @@ -320,11 +321,10 @@ | |
| 321 | <li><a href="javascript.md"><b>Use of JavaScript in Fossil</b></a></li> |
| 322 | <li><a href="fiveminutes.wiki">User — Up and Running in 5 Minutes as a Single</a></li> |
| 323 | <li><a href="caps/">User Capabilities — Administering</a></li> |
| 324 | <li><a href="caps/ref.html"><b>User Capability Reference</b></a></li> |
| 325 | <li><a href="caps/admin-v-setup.md">Users — Differences Between Setup and Admin</a></li> |
| 326 | <li><a href="serverext.wiki">Using CGI Scripts — Adding Extensions To A Fossil Server</a></li> |
| 327 | <li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li> |
| 328 | <li><a href="env-opts.md">Variables and Global Options — Environment</a></li> |
| 329 | <li><a href="whyusefossil.wiki">Version Control — Benefits Of</a></li> |
| 330 | <li><a href="checkin_names.wiki">Version Names — Check-in And</a></li> |
| @@ -338,9 +338,10 @@ | |
| 338 | <li><a href="../../../help">Webpages — Lists of Commands and</a></li> |
| 339 | <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> |
| 340 | <li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li> |
| 341 | <li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li> |
| 342 | <li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li> |
| 343 | <li><a href="ckout-workflows.md">Workflows — Check-Out</a></li> |
| 344 | <li><a href="aboutdownload.wiki">Works — How The Download Page</a></li> |
| 345 | <li><a href="aboutcgi.wiki">Works In Fossil — How CGI</a></li> |
| 346 | <li><a href="whyusefossil.wiki">You Should Use Fossil — Why</a></li> |
| 347 | </ul></div> |
| 348 |
+21
-1
| --- www/serverext.wiki | ||
| +++ www/serverext.wiki | ||
| @@ -274,11 +274,31 @@ | ||
| 274 | 274 | If a CGI program requires separate data files, it is safe to put those |
| 275 | 275 | files in the same directory as the CGI program itself as long as the names |
| 276 | 276 | of the data files contain special characters that cause them to be ignored |
| 277 | 277 | by Fossil. |
| 278 | 278 | |
| 279 | -<h2>6.0 Trouble-Shooting Hints</h2> | |
| 279 | +<h2>6.0 Access Permissions</h2> | |
| 280 | + | |
| 281 | +CGI extension files and programs are accessible to everyone. | |
| 282 | + | |
| 283 | +When CGI extensions have been enabled (using either "extroot:" in the | |
| 284 | +CGI file or the --extroot option for other server methods) all files | |
| 285 | +in the extension root directory hierarchy, except special filenames | |
| 286 | +identified previously, are accessible to all users. Users do not | |
| 287 | +have to have "Read" privilege, or any other privilege, in order to | |
| 288 | +access the extensions. | |
| 289 | + | |
| 290 | +This is by design. The CGI extension mechanism is intended to operate | |
| 291 | +in the same way as a traditional web-server. | |
| 292 | + | |
| 293 | +CGI programs that want to restrict access | |
| 294 | +can examine the FOSSIL_CAPABILITIES and/or FOSSIL_USER environment variables. | |
| 295 | +In other words, access control is the responsibility of the individual | |
| 296 | +extension programs. | |
| 297 | + | |
| 298 | + | |
| 299 | +<h2>7.0 Trouble-Shooting Hints</h2> | |
| 280 | 300 | |
| 281 | 301 | Remember that the /ext will return any file in the extroot directory |
| 282 | 302 | hierarchy as static content if the file is readable but not executable. |
| 283 | 303 | When initially setting up the /ext mechanism, it is sometimes helpful |
| 284 | 304 | to verify that you are able to receive static content prior to starting |
| 285 | 305 |
| --- www/serverext.wiki | |
| +++ www/serverext.wiki | |
| @@ -274,11 +274,31 @@ | |
| 274 | If a CGI program requires separate data files, it is safe to put those |
| 275 | files in the same directory as the CGI program itself as long as the names |
| 276 | of the data files contain special characters that cause them to be ignored |
| 277 | by Fossil. |
| 278 | |
| 279 | <h2>6.0 Trouble-Shooting Hints</h2> |
| 280 | |
| 281 | Remember that the /ext will return any file in the extroot directory |
| 282 | hierarchy as static content if the file is readable but not executable. |
| 283 | When initially setting up the /ext mechanism, it is sometimes helpful |
| 284 | to verify that you are able to receive static content prior to starting |
| 285 |
| --- www/serverext.wiki | |
| +++ www/serverext.wiki | |
| @@ -274,11 +274,31 @@ | |
| 274 | If a CGI program requires separate data files, it is safe to put those |
| 275 | files in the same directory as the CGI program itself as long as the names |
| 276 | of the data files contain special characters that cause them to be ignored |
| 277 | by Fossil. |
| 278 | |
| 279 | <h2>6.0 Access Permissions</h2> |
| 280 | |
| 281 | CGI extension files and programs are accessible to everyone. |
| 282 | |
| 283 | When CGI extensions have been enabled (using either "extroot:" in the |
| 284 | CGI file or the --extroot option for other server methods) all files |
| 285 | in the extension root directory hierarchy, except special filenames |
| 286 | identified previously, are accessible to all users. Users do not |
| 287 | have to have "Read" privilege, or any other privilege, in order to |
| 288 | access the extensions. |
| 289 | |
| 290 | This is by design. The CGI extension mechanism is intended to operate |
| 291 | in the same way as a traditional web-server. |
| 292 | |
| 293 | CGI programs that want to restrict access |
| 294 | can examine the FOSSIL_CAPABILITIES and/or FOSSIL_USER environment variables. |
| 295 | In other words, access control is the responsibility of the individual |
| 296 | extension programs. |
| 297 | |
| 298 | |
| 299 | <h2>7.0 Trouble-Shooting Hints</h2> |
| 300 | |
| 301 | Remember that the /ext will return any file in the extroot directory |
| 302 | hierarchy as static content if the file is readable but not executable. |
| 303 | When initially setting up the /ext mechanism, it is sometimes helpful |
| 304 | to verify that you are able to receive static content prior to starting |
| 305 |
+17
| --- www/shunning.wiki | ||
| +++ www/shunning.wiki | ||
| @@ -19,10 +19,17 @@ | ||
| 19 | 19 | copyright was accidentally committed and needs to be backed out. |
| 20 | 20 | |
| 21 | 21 | * A malformed control artifact was inserted and is disrupting the |
| 22 | 22 | operation of Fossil. |
| 23 | 23 | |
| 24 | + * A legitimate legal request was received requiring content to | |
| 25 | + be removed. This would most likely be related to the accidental | |
| 26 | + intellectual property error or spam cases listed above. Some countries | |
| 27 | + recognise software patents, and so allow legal claims targetting code | |
| 28 | + commits. Some countries can require publicly-available encryption | |
| 29 | + software to be taken down if it is committed to the DAG without | |
| 30 | + the correct government authorisation. | |
| 24 | 31 | |
| 25 | 32 | <h2>Alternatives</h2> |
| 26 | 33 | |
| 27 | 34 | All of these are rare cases: Fossil is [./antibot.wiki | designed to |
| 28 | 35 | foil spammers up front], legally problematic check-ins should range from |
| @@ -81,10 +88,20 @@ | ||
| 81 | 88 | repository. Again, nothing is actually deleted; you're just adding |
| 82 | 89 | more information to the repository which corrects a prior |
| 83 | 90 | check-in.</p></li> |
| 84 | 91 | </ul> |
| 85 | 92 | |
| 93 | +<h2>Exception: Non-versioned Content</h2> | |
| 94 | + | |
| 95 | +It is normal and expected to delete data which is not versioned, such as | |
| 96 | +usernames and passwords in the user table. The [/help/scrub|fossil scrub] | |
| 97 | +command will remove all sensitive non-versioned data from a respository. | |
| 98 | + | |
| 99 | +The scrub command will remove user 'bertina', along with their password, | |
| 100 | +any supplied IP address, any concealed email address etc. However, in the | |
| 101 | +DAG, commits by 'bertina' will continue to be visible unchanged even though | |
| 102 | +there is no longer any such user in Fossil. | |
| 86 | 103 | |
| 87 | 104 | <h2>Shunning</h2> |
| 88 | 105 | |
| 89 | 106 | Fossil provides a mechanism called "shunning" for removing content from |
| 90 | 107 | a repository. |
| 91 | 108 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -19,10 +19,17 @@ | |
| 19 | copyright was accidentally committed and needs to be backed out. |
| 20 | |
| 21 | * A malformed control artifact was inserted and is disrupting the |
| 22 | operation of Fossil. |
| 23 | |
| 24 | |
| 25 | <h2>Alternatives</h2> |
| 26 | |
| 27 | All of these are rare cases: Fossil is [./antibot.wiki | designed to |
| 28 | foil spammers up front], legally problematic check-ins should range from |
| @@ -81,10 +88,20 @@ | |
| 81 | repository. Again, nothing is actually deleted; you're just adding |
| 82 | more information to the repository which corrects a prior |
| 83 | check-in.</p></li> |
| 84 | </ul> |
| 85 | |
| 86 | |
| 87 | <h2>Shunning</h2> |
| 88 | |
| 89 | Fossil provides a mechanism called "shunning" for removing content from |
| 90 | a repository. |
| 91 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -19,10 +19,17 @@ | |
| 19 | copyright was accidentally committed and needs to be backed out. |
| 20 | |
| 21 | * A malformed control artifact was inserted and is disrupting the |
| 22 | operation of Fossil. |
| 23 | |
| 24 | * A legitimate legal request was received requiring content to |
| 25 | be removed. This would most likely be related to the accidental |
| 26 | intellectual property error or spam cases listed above. Some countries |
| 27 | recognise software patents, and so allow legal claims targetting code |
| 28 | commits. Some countries can require publicly-available encryption |
| 29 | software to be taken down if it is committed to the DAG without |
| 30 | the correct government authorisation. |
| 31 | |
| 32 | <h2>Alternatives</h2> |
| 33 | |
| 34 | All of these are rare cases: Fossil is [./antibot.wiki | designed to |
| 35 | foil spammers up front], legally problematic check-ins should range from |
| @@ -81,10 +88,20 @@ | |
| 88 | repository. Again, nothing is actually deleted; you're just adding |
| 89 | more information to the repository which corrects a prior |
| 90 | check-in.</p></li> |
| 91 | </ul> |
| 92 | |
| 93 | <h2>Exception: Non-versioned Content</h2> |
| 94 | |
| 95 | It is normal and expected to delete data which is not versioned, such as |
| 96 | usernames and passwords in the user table. The [/help/scrub|fossil scrub] |
| 97 | command will remove all sensitive non-versioned data from a respository. |
| 98 | |
| 99 | The scrub command will remove user 'bertina', along with their password, |
| 100 | any supplied IP address, any concealed email address etc. However, in the |
| 101 | DAG, commits by 'bertina' will continue to be visible unchanged even though |
| 102 | there is no longer any such user in Fossil. |
| 103 | |
| 104 | <h2>Shunning</h2> |
| 105 | |
| 106 | Fossil provides a mechanism called "shunning" for removing content from |
| 107 | a repository. |
| 108 |