Fossil SCM
Prototype for one approach to linking forum posts to other artifacts (initially check-ins). Adds the --forumpost HASH flag to the ci command, which adds a forumpost/FULL-HASH tag to the checkin for later use in /info and forum post views. For ease of use, this probably needs to be adapted to map only to the first version of a forum post, as is done in the forumpost-locking branch, once that branch is merged with trunk.
Commit
3e5d23daec90eb93de3f21ed79f5284b98caa63b1edc3c125fe3c0c9a3d68ebd
Parent
4717db33f0033b4…
1 file changed
+32
-11
+32
-11
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -1817,12 +1817,12 @@ | ||
| 1817 | 1817 | |
| 1818 | 1818 | if( p->azTag ){ |
| 1819 | 1819 | for(i=0; p->azTag[i]; i++){ |
| 1820 | 1820 | /* Add a symbolic tag to this check-in. The tag names have already |
| 1821 | 1821 | ** been sorted and converted using the %F format */ |
| 1822 | - assert( i==0 || strcmp(p->azTag[i-1], p->azTag[i])<=0 ); | |
| 1823 | - blob_appendf(pOut, "T +sym-%s *\n", p->azTag[i]); | |
| 1822 | + assert( i==0 || fossil_strcmp(p->azTag[i-1], p->azTag[i])<=0 ); | |
| 1823 | + blob_appendf(pOut, "T +%s *\n", p->azTag[i]); | |
| 1824 | 1824 | } |
| 1825 | 1825 | } |
| 1826 | 1826 | if( p->zBranch && p->zBranch[0] ){ |
| 1827 | 1827 | /* For a new branch, cancel all prior propagating tags */ |
| 1828 | 1828 | db_prepare(&q, |
| @@ -2088,10 +2088,22 @@ | ||
| 2088 | 2088 | static int tagCmp(const void *a, const void *b){ |
| 2089 | 2089 | char **pA = (char**)a; |
| 2090 | 2090 | char **pB = (char**)b; |
| 2091 | 2091 | return fossil_strcmp(pA[0], pB[0]); |
| 2092 | 2092 | } |
| 2093 | + | |
| 2094 | +/* | |
| 2095 | +** Append zTag at pCi->azTag[*pNTag] (reallocating as needed), | |
| 2096 | +** increment *pNTag, then set pCi->azTag[*pNTag] to 0. | |
| 2097 | +*/ | |
| 2098 | +static void ci_append_tag(CheckinInfo *pCi, int *pNTag, | |
| 2099 | + const char *zTag){ | |
| 2100 | + pCi->azTag = fossil_realloc((void*)pCi->azTag, | |
| 2101 | + sizeof(char*)*(*pNTag+2)); | |
| 2102 | + pCi->azTag[(*pNTag)++] = zTag; | |
| 2103 | + pCi->azTag[*pNTag] = 0; | |
| 2104 | +} | |
| 2093 | 2105 | |
| 2094 | 2106 | /* |
| 2095 | 2107 | ** COMMAND: ci# |
| 2096 | 2108 | ** COMMAND: commit |
| 2097 | 2109 | ** |
| @@ -2161,10 +2173,12 @@ | ||
| 2161 | 2173 | ** ("auto" lets Fossil choose it automatically, |
| 2162 | 2174 | ** even for private branches) |
| 2163 | 2175 | ** --close Close the branch being committed |
| 2164 | 2176 | ** --date-override DATETIME DATE to use instead of 'now' |
| 2165 | 2177 | ** --delta Use a delta manifest in the commit process |
| 2178 | +** --forumpost HASH Adds a tag linking the given forum post to | |
| 2179 | +** this check-in. May be given multiple times. | |
| 2166 | 2180 | ** --hash Verify file status using hashing rather |
| 2167 | 2181 | ** than relying on file mtimes |
| 2168 | 2182 | ** --ignore-clock-skew If a clock skew is detected, ignore it and |
| 2169 | 2183 | ** behave as if the user had entered 'yes' to |
| 2170 | 2184 | ** the question of whether to proceed despite |
| @@ -2182,11 +2196,12 @@ | ||
| 2182 | 2196 | ** --no-warnings Omit all warnings about file contents |
| 2183 | 2197 | ** --no-verify Do not run before-commit hooks |
| 2184 | 2198 | ** --nosign Do not attempt to sign this commit with gpg |
| 2185 | 2199 | ** --override-lock Allow a check-in even though parent is locked |
| 2186 | 2200 | ** --private Do not sync changes and their descendants |
| 2187 | -** --tag TAG-NAME Assign given tag TAG-NAME to the check-in | |
| 2201 | +** --tag TAG-NAME Assign given tag TAG-NAME to the check-in. May | |
| 2202 | +** be given multiple times. | |
| 2188 | 2203 | ** --trace Debug tracing |
| 2189 | 2204 | ** --user-override USER USER to use instead of the current default |
| 2190 | 2205 | ** |
| 2191 | 2206 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 2192 | 2207 | ** year-month-day form, it may be truncated, the "T" may be replaced by |
| @@ -2292,14 +2307,23 @@ | ||
| 2292 | 2307 | sCiInfo.integrateFlag = find_option("integrate",0,0)!=0; |
| 2293 | 2308 | sCiInfo.zMimetype = find_option("mimetype",0,1); |
| 2294 | 2309 | sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0; |
| 2295 | 2310 | while( (zTag = find_option("tag",0,1))!=0 ){ |
| 2296 | 2311 | if( zTag[0]==0 ) continue; |
| 2297 | - sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag, | |
| 2298 | - sizeof(char*)*(nTag+2)); | |
| 2299 | - sCiInfo.azTag[nTag++] = zTag; | |
| 2300 | - sCiInfo.azTag[nTag] = 0; | |
| 2312 | + ci_append_tag(&sCiInfo, &nTag, mprintf("sym-%F",zTag)); | |
| 2313 | + } | |
| 2314 | + while( (zTag = find_option("forumpost",0,1))!=0 ){ | |
| 2315 | + int forumRid; | |
| 2316 | + if( zTag[0]==0 ) continue; | |
| 2317 | + forumRid = symbolic_name_to_rid(zTag, "f"); | |
| 2318 | + if( forumRid==0 ){ | |
| 2319 | + fossil_fatal("Not a forum post: %s", zTag); | |
| 2320 | + }else if( forumRid<0 ){ | |
| 2321 | + fossil_fatal("Ambiguous symbolic name: %s", zTag); | |
| 2322 | + } | |
| 2323 | + ci_append_tag(&sCiInfo, &nTag, | |
| 2324 | + mprintf("forumpost/%z", rid_to_uuid(forumRid))); | |
| 2301 | 2325 | } |
| 2302 | 2326 | zComFile = find_option("message-file", "M", 1); |
| 2303 | 2327 | sCiInfo.zDateOvrd = find_option("date-override",0,1); |
| 2304 | 2328 | sCiInfo.zUserOvrd = find_option("user-override",0,1); |
| 2305 | 2329 | noSign = db_get_boolean("omitsign", 0)|noSign; |
| @@ -2345,12 +2369,10 @@ | ||
| 2345 | 2369 | " to override", sCiInfo.zBranch); |
| 2346 | 2370 | } |
| 2347 | 2371 | |
| 2348 | 2372 | /* Escape special characters in tags and put all tags in sorted order */ |
| 2349 | 2373 | if( nTag ){ |
| 2350 | - int i; | |
| 2351 | - for(i=0; i<nTag; i++) sCiInfo.azTag[i] = mprintf("%F", sCiInfo.azTag[i]); | |
| 2352 | 2374 | qsort((void*)sCiInfo.azTag, nTag, sizeof(sCiInfo.azTag[0]), tagCmp); |
| 2353 | 2375 | } |
| 2354 | 2376 | |
| 2355 | 2377 | /* |
| 2356 | 2378 | ** Autosync if autosync is enabled and this is not a private check-in. |
| @@ -2511,11 +2533,11 @@ | ||
| 2511 | 2533 | }else{ |
| 2512 | 2534 | fossil_fatal("Would fork. \"update\" first or use --branch or " |
| 2513 | 2535 | "--allow-fork."); |
| 2514 | 2536 | } |
| 2515 | 2537 | } |
| 2516 | - | |
| 2538 | + | |
| 2517 | 2539 | /* |
| 2518 | 2540 | ** Do not allow a commit against a closed leaf unless the commit |
| 2519 | 2541 | ** ends up on a different branch. |
| 2520 | 2542 | */ |
| 2521 | 2543 | if( |
| @@ -2532,11 +2554,10 @@ | ||
| 2532 | 2554 | } |
| 2533 | 2555 | |
| 2534 | 2556 | /* Always exit the loop on the second pass */ |
| 2535 | 2557 | if( bRecheck ) break; |
| 2536 | 2558 | |
| 2537 | - | |
| 2538 | 2559 | /* Get the check-in comment. This might involve prompting the |
| 2539 | 2560 | ** user for the check-in comment, in which case we should resync |
| 2540 | 2561 | ** to renew the check-in lock and repeat the checks for conflicts. |
| 2541 | 2562 | */ |
| 2542 | 2563 | if( zComment ){ |
| 2543 | 2564 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1817,12 +1817,12 @@ | |
| 1817 | |
| 1818 | if( p->azTag ){ |
| 1819 | for(i=0; p->azTag[i]; i++){ |
| 1820 | /* Add a symbolic tag to this check-in. The tag names have already |
| 1821 | ** been sorted and converted using the %F format */ |
| 1822 | assert( i==0 || strcmp(p->azTag[i-1], p->azTag[i])<=0 ); |
| 1823 | blob_appendf(pOut, "T +sym-%s *\n", p->azTag[i]); |
| 1824 | } |
| 1825 | } |
| 1826 | if( p->zBranch && p->zBranch[0] ){ |
| 1827 | /* For a new branch, cancel all prior propagating tags */ |
| 1828 | db_prepare(&q, |
| @@ -2088,10 +2088,22 @@ | |
| 2088 | static int tagCmp(const void *a, const void *b){ |
| 2089 | char **pA = (char**)a; |
| 2090 | char **pB = (char**)b; |
| 2091 | return fossil_strcmp(pA[0], pB[0]); |
| 2092 | } |
| 2093 | |
| 2094 | /* |
| 2095 | ** COMMAND: ci# |
| 2096 | ** COMMAND: commit |
| 2097 | ** |
| @@ -2161,10 +2173,12 @@ | |
| 2161 | ** ("auto" lets Fossil choose it automatically, |
| 2162 | ** even for private branches) |
| 2163 | ** --close Close the branch being committed |
| 2164 | ** --date-override DATETIME DATE to use instead of 'now' |
| 2165 | ** --delta Use a delta manifest in the commit process |
| 2166 | ** --hash Verify file status using hashing rather |
| 2167 | ** than relying on file mtimes |
| 2168 | ** --ignore-clock-skew If a clock skew is detected, ignore it and |
| 2169 | ** behave as if the user had entered 'yes' to |
| 2170 | ** the question of whether to proceed despite |
| @@ -2182,11 +2196,12 @@ | |
| 2182 | ** --no-warnings Omit all warnings about file contents |
| 2183 | ** --no-verify Do not run before-commit hooks |
| 2184 | ** --nosign Do not attempt to sign this commit with gpg |
| 2185 | ** --override-lock Allow a check-in even though parent is locked |
| 2186 | ** --private Do not sync changes and their descendants |
| 2187 | ** --tag TAG-NAME Assign given tag TAG-NAME to the check-in |
| 2188 | ** --trace Debug tracing |
| 2189 | ** --user-override USER USER to use instead of the current default |
| 2190 | ** |
| 2191 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 2192 | ** year-month-day form, it may be truncated, the "T" may be replaced by |
| @@ -2292,14 +2307,23 @@ | |
| 2292 | sCiInfo.integrateFlag = find_option("integrate",0,0)!=0; |
| 2293 | sCiInfo.zMimetype = find_option("mimetype",0,1); |
| 2294 | sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0; |
| 2295 | while( (zTag = find_option("tag",0,1))!=0 ){ |
| 2296 | if( zTag[0]==0 ) continue; |
| 2297 | sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag, |
| 2298 | sizeof(char*)*(nTag+2)); |
| 2299 | sCiInfo.azTag[nTag++] = zTag; |
| 2300 | sCiInfo.azTag[nTag] = 0; |
| 2301 | } |
| 2302 | zComFile = find_option("message-file", "M", 1); |
| 2303 | sCiInfo.zDateOvrd = find_option("date-override",0,1); |
| 2304 | sCiInfo.zUserOvrd = find_option("user-override",0,1); |
| 2305 | noSign = db_get_boolean("omitsign", 0)|noSign; |
| @@ -2345,12 +2369,10 @@ | |
| 2345 | " to override", sCiInfo.zBranch); |
| 2346 | } |
| 2347 | |
| 2348 | /* Escape special characters in tags and put all tags in sorted order */ |
| 2349 | if( nTag ){ |
| 2350 | int i; |
| 2351 | for(i=0; i<nTag; i++) sCiInfo.azTag[i] = mprintf("%F", sCiInfo.azTag[i]); |
| 2352 | qsort((void*)sCiInfo.azTag, nTag, sizeof(sCiInfo.azTag[0]), tagCmp); |
| 2353 | } |
| 2354 | |
| 2355 | /* |
| 2356 | ** Autosync if autosync is enabled and this is not a private check-in. |
| @@ -2511,11 +2533,11 @@ | |
| 2511 | }else{ |
| 2512 | fossil_fatal("Would fork. \"update\" first or use --branch or " |
| 2513 | "--allow-fork."); |
| 2514 | } |
| 2515 | } |
| 2516 | |
| 2517 | /* |
| 2518 | ** Do not allow a commit against a closed leaf unless the commit |
| 2519 | ** ends up on a different branch. |
| 2520 | */ |
| 2521 | if( |
| @@ -2532,11 +2554,10 @@ | |
| 2532 | } |
| 2533 | |
| 2534 | /* Always exit the loop on the second pass */ |
| 2535 | if( bRecheck ) break; |
| 2536 | |
| 2537 | |
| 2538 | /* Get the check-in comment. This might involve prompting the |
| 2539 | ** user for the check-in comment, in which case we should resync |
| 2540 | ** to renew the check-in lock and repeat the checks for conflicts. |
| 2541 | */ |
| 2542 | if( zComment ){ |
| 2543 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1817,12 +1817,12 @@ | |
| 1817 | |
| 1818 | if( p->azTag ){ |
| 1819 | for(i=0; p->azTag[i]; i++){ |
| 1820 | /* Add a symbolic tag to this check-in. The tag names have already |
| 1821 | ** been sorted and converted using the %F format */ |
| 1822 | assert( i==0 || fossil_strcmp(p->azTag[i-1], p->azTag[i])<=0 ); |
| 1823 | blob_appendf(pOut, "T +%s *\n", p->azTag[i]); |
| 1824 | } |
| 1825 | } |
| 1826 | if( p->zBranch && p->zBranch[0] ){ |
| 1827 | /* For a new branch, cancel all prior propagating tags */ |
| 1828 | db_prepare(&q, |
| @@ -2088,10 +2088,22 @@ | |
| 2088 | static int tagCmp(const void *a, const void *b){ |
| 2089 | char **pA = (char**)a; |
| 2090 | char **pB = (char**)b; |
| 2091 | return fossil_strcmp(pA[0], pB[0]); |
| 2092 | } |
| 2093 | |
| 2094 | /* |
| 2095 | ** Append zTag at pCi->azTag[*pNTag] (reallocating as needed), |
| 2096 | ** increment *pNTag, then set pCi->azTag[*pNTag] to 0. |
| 2097 | */ |
| 2098 | static void ci_append_tag(CheckinInfo *pCi, int *pNTag, |
| 2099 | const char *zTag){ |
| 2100 | pCi->azTag = fossil_realloc((void*)pCi->azTag, |
| 2101 | sizeof(char*)*(*pNTag+2)); |
| 2102 | pCi->azTag[(*pNTag)++] = zTag; |
| 2103 | pCi->azTag[*pNTag] = 0; |
| 2104 | } |
| 2105 | |
| 2106 | /* |
| 2107 | ** COMMAND: ci# |
| 2108 | ** COMMAND: commit |
| 2109 | ** |
| @@ -2161,10 +2173,12 @@ | |
| 2173 | ** ("auto" lets Fossil choose it automatically, |
| 2174 | ** even for private branches) |
| 2175 | ** --close Close the branch being committed |
| 2176 | ** --date-override DATETIME DATE to use instead of 'now' |
| 2177 | ** --delta Use a delta manifest in the commit process |
| 2178 | ** --forumpost HASH Adds a tag linking the given forum post to |
| 2179 | ** this check-in. May be given multiple times. |
| 2180 | ** --hash Verify file status using hashing rather |
| 2181 | ** than relying on file mtimes |
| 2182 | ** --ignore-clock-skew If a clock skew is detected, ignore it and |
| 2183 | ** behave as if the user had entered 'yes' to |
| 2184 | ** the question of whether to proceed despite |
| @@ -2182,11 +2196,12 @@ | |
| 2196 | ** --no-warnings Omit all warnings about file contents |
| 2197 | ** --no-verify Do not run before-commit hooks |
| 2198 | ** --nosign Do not attempt to sign this commit with gpg |
| 2199 | ** --override-lock Allow a check-in even though parent is locked |
| 2200 | ** --private Do not sync changes and their descendants |
| 2201 | ** --tag TAG-NAME Assign given tag TAG-NAME to the check-in. May |
| 2202 | ** be given multiple times. |
| 2203 | ** --trace Debug tracing |
| 2204 | ** --user-override USER USER to use instead of the current default |
| 2205 | ** |
| 2206 | ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in |
| 2207 | ** year-month-day form, it may be truncated, the "T" may be replaced by |
| @@ -2292,14 +2307,23 @@ | |
| 2307 | sCiInfo.integrateFlag = find_option("integrate",0,0)!=0; |
| 2308 | sCiInfo.zMimetype = find_option("mimetype",0,1); |
| 2309 | sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0; |
| 2310 | while( (zTag = find_option("tag",0,1))!=0 ){ |
| 2311 | if( zTag[0]==0 ) continue; |
| 2312 | ci_append_tag(&sCiInfo, &nTag, mprintf("sym-%F",zTag)); |
| 2313 | } |
| 2314 | while( (zTag = find_option("forumpost",0,1))!=0 ){ |
| 2315 | int forumRid; |
| 2316 | if( zTag[0]==0 ) continue; |
| 2317 | forumRid = symbolic_name_to_rid(zTag, "f"); |
| 2318 | if( forumRid==0 ){ |
| 2319 | fossil_fatal("Not a forum post: %s", zTag); |
| 2320 | }else if( forumRid<0 ){ |
| 2321 | fossil_fatal("Ambiguous symbolic name: %s", zTag); |
| 2322 | } |
| 2323 | ci_append_tag(&sCiInfo, &nTag, |
| 2324 | mprintf("forumpost/%z", rid_to_uuid(forumRid))); |
| 2325 | } |
| 2326 | zComFile = find_option("message-file", "M", 1); |
| 2327 | sCiInfo.zDateOvrd = find_option("date-override",0,1); |
| 2328 | sCiInfo.zUserOvrd = find_option("user-override",0,1); |
| 2329 | noSign = db_get_boolean("omitsign", 0)|noSign; |
| @@ -2345,12 +2369,10 @@ | |
| 2369 | " to override", sCiInfo.zBranch); |
| 2370 | } |
| 2371 | |
| 2372 | /* Escape special characters in tags and put all tags in sorted order */ |
| 2373 | if( nTag ){ |
| 2374 | qsort((void*)sCiInfo.azTag, nTag, sizeof(sCiInfo.azTag[0]), tagCmp); |
| 2375 | } |
| 2376 | |
| 2377 | /* |
| 2378 | ** Autosync if autosync is enabled and this is not a private check-in. |
| @@ -2511,11 +2533,11 @@ | |
| 2533 | }else{ |
| 2534 | fossil_fatal("Would fork. \"update\" first or use --branch or " |
| 2535 | "--allow-fork."); |
| 2536 | } |
| 2537 | } |
| 2538 | |
| 2539 | /* |
| 2540 | ** Do not allow a commit against a closed leaf unless the commit |
| 2541 | ** ends up on a different branch. |
| 2542 | */ |
| 2543 | if( |
| @@ -2532,11 +2554,10 @@ | |
| 2554 | } |
| 2555 | |
| 2556 | /* Always exit the loop on the second pass */ |
| 2557 | if( bRecheck ) break; |
| 2558 | |
| 2559 | /* Get the check-in comment. This might involve prompting the |
| 2560 | ** user for the check-in comment, in which case we should resync |
| 2561 | ** to renew the check-in lock and repeat the checks for conflicts. |
| 2562 | */ |
| 2563 | if( zComment ){ |
| 2564 |