Fossil SCM
Re-do previous checkin - i had been editing the generated bld/manifest_.c because of PEBKAC caused by following a compilation error into that file.
Commit
069995d7eaf52c67b3b73cd176a30fc048940b5e039c0318e3d082bb7736f316
Parent
e3e8fa351b9649b…
1 file changed
+151
-15
+151
-15
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -2911,37 +2911,173 @@ | ||
| 2911 | 2911 | if( g.argc!=3 ) usage("RECORDID"); |
| 2912 | 2912 | rid = name_to_rid(g.argv[2]); |
| 2913 | 2913 | content_get(rid, &content); |
| 2914 | 2914 | manifest_crosslink(rid, &content, MC_NONE); |
| 2915 | 2915 | } |
| 2916 | + | |
| 2917 | +/* | |
| 2918 | +** For a given CATYPE_... value, returns a human-friendly name, or | |
| 2919 | +** NULL if typeId is unknown or is CFTYPE_ANY. | |
| 2920 | +*/ | |
| 2921 | +const char * artifact_type_to_name(int typeId){ | |
| 2922 | + switch(typeId){ | |
| 2923 | + case CFTYPE_MANIFEST: return "checkin"; | |
| 2924 | + case CFTYPE_CLUSTER: return "cluster"; | |
| 2925 | + case CFTYPE_CONTROL: return "control"; | |
| 2926 | + case CFTYPE_WIKI: return "wiki"; | |
| 2927 | + case CFTYPE_TICKET: return "ticket"; | |
| 2928 | + case CFTYPE_ATTACHMENT: return "attachment"; | |
| 2929 | + case CFTYPE_EVENT: return "event"; | |
| 2930 | + case CFTYPE_FORUM: return "forumpost"; | |
| 2931 | + } | |
| 2932 | + return NULL; | |
| 2933 | +} | |
| 2916 | 2934 | |
| 2917 | 2935 | /* |
| 2918 | 2936 | ** Creates a JSON representation of p, appending it to pOut. |
| 2937 | +** | |
| 2938 | +** Pedantic note: this routine traverses p->aFile directly, rather than | |
| 2939 | +** using manifest_file_next(), so that delta manifests are rendered as-is | |
| 2940 | +** instead of having their derived files. If that policy is ever changed, | |
| 2941 | +** p will need to be non-const. | |
| 2919 | 2942 | */ |
| 2920 | -void artifact_to_json(Manifest *p, Blob *pOut){ | |
| 2921 | - char * zTmp; | |
| 2922 | - blob_append_literal(pOut, "{"); | |
| 2923 | - blob_appendf(pOut, "\"rid\": %d", p->rid); | |
| 2924 | - zTmp = rid_to_uuid(p->rid); | |
| 2925 | - blob_appendf(pOut, ", \"uuid\": %!j", zTmp); | |
| 2926 | - fossil_free(zTmp); | |
| 2927 | -#define CARD_FMT(LETTER, FMT, VAL) \ | |
| 2928 | - blob_appendf(pOut, ",\"" #LETTER "\": " #FMT, VAL) | |
| 2943 | +void artifact_to_json(Manifest const *p, Blob *b){ | |
| 2944 | + int i; | |
| 2945 | + char *zUuid; | |
| 2946 | + | |
| 2947 | + blob_append_literal(b, "{"); | |
| 2948 | + blob_appendf(b, "\"rid\": %d", p->rid); | |
| 2949 | + zUuid = rid_to_uuid(p->rid); | |
| 2950 | + blob_appendf(b, ", \"uuid\": %!j", zUuid); | |
| 2951 | + blob_appendf(b, ", \"type\": %!j", artifact_type_to_name(p->type)); | |
| 2952 | +#define ISA(TYPE) if( p->type==TYPE ) | |
| 2953 | +#define CARD_LETTER(LETTER) \ | |
| 2954 | + blob_append_literal(b, ",\"" #LETTER "\": ") | |
| 2929 | 2955 | #define CARD_STR(LETTER, VAL) \ |
| 2930 | - assert( VAL ); CARD_FMT(LETTER, %!j, VAL) | |
| 2956 | + assert( VAL ); CARD_LETTER(LETTER); blob_appendf(b, "%!j", VAL) | |
| 2931 | 2957 | #define CARD_STR2(LETTER, VAL) \ |
| 2932 | - if( VAL ) { CARD_FMT(LETTER, %!j, VAL); } | |
| 2958 | + if( VAL ) { CARD_STR(LETTER, VAL); } (void)0 | |
| 2959 | +#define STR_OR_NULL(VAL) \ | |
| 2960 | + if( VAL ) blob_appendf(b, "%!j", VAL); \ | |
| 2961 | + else blob_append(b, "null", 4) | |
| 2962 | +#define KVP_STR(ADDCOMMA, KEY,VAL) \ | |
| 2963 | + if(ADDCOMMA) blob_append_char(b, ','); \ | |
| 2964 | + blob_appendf(b, "%!j: ", #KEY); \ | |
| 2965 | + STR_OR_NULL(VAL) | |
| 2933 | 2966 | |
| 2967 | + /* Noting that only 1 (at most) of the A-card pieces will be non-NULL... */ | |
| 2968 | + ISA( CFTYPE_ATTACHMENT ){ | |
| 2969 | + CARD_LETTER(A); | |
| 2970 | + blob_append_char(b, '{'); | |
| 2971 | + KVP_STR(0, filename, p->zAttachName); | |
| 2972 | + KVP_STR(1, target, p->zAttachTarget); | |
| 2973 | + KVP_STR(1, source, p->zAttachSrc); | |
| 2974 | + blob_append_char(b, '}'); | |
| 2975 | + } | |
| 2934 | 2976 | CARD_STR2(B, p->zBaseline); |
| 2935 | 2977 | CARD_STR2(C, p->zComment); |
| 2936 | - CARD_FMT(D, %f, p->rDate); | |
| 2937 | - CARD_STR2(W, p->zWiki); | |
| 2978 | + CARD_LETTER(D); blob_appendf(b, "%f", p->rDate); | |
| 2979 | + ISA( CFTYPE_EVENT ){ | |
| 2980 | + blob_appendf(b, ", \"E\": {\"time\": %f, \"id\": %!j}", | |
| 2981 | + p->rEventDate, p->zEventId); | |
| 2982 | + } | |
| 2983 | + ISA( CFTYPE_MANIFEST ){ | |
| 2984 | + CARD_LETTER(F); | |
| 2985 | + blob_append_char(b, '['); | |
| 2986 | + for( i = 0; i < p->nFile; ++i ){ | |
| 2987 | + ManifestFile const * const pF = &p->aFile[i]; | |
| 2988 | + if( i>0 ) blob_append_char(b, ','); | |
| 2989 | + blob_append_char(b, '{'); | |
| 2990 | + KVP_STR(0, name, pF->zName); | |
| 2991 | + KVP_STR(1, uuid, pF->zUuid); | |
| 2992 | + KVP_STR(1, perm, pF->zPerm); | |
| 2993 | + KVP_STR(1, oldName, pF->zPrior); | |
| 2994 | + blob_append_char(b, '}'); | |
| 2995 | + } | |
| 2996 | + blob_append_char(b, ']'); | |
| 2997 | + } | |
| 2998 | + CARD_STR2(G, p->zThreadRoot); | |
| 2999 | + CARD_STR2(H, p->zThreadTitle); | |
| 3000 | + CARD_STR2(I, p->zInReplyTo); | |
| 3001 | + if( p->nField ){ | |
| 3002 | + CARD_LETTER(J); | |
| 3003 | + blob_append_char(b, '['); | |
| 3004 | + for( i = 0; i < p->nField; ++i ){ | |
| 3005 | + if( i>0 ) blob_append_char(b, ','); | |
| 3006 | + blob_append_char(b, '{'); | |
| 3007 | + KVP_STR(0, name, p->aField[i].zName); | |
| 3008 | + KVP_STR(1, value, p->aField[i].zValue); | |
| 3009 | + blob_append_char(b, '}'); | |
| 3010 | + } | |
| 3011 | + blob_append_char(b, ']'); | |
| 3012 | + } | |
| 3013 | + CARD_STR2(K, p->zTicketUuid); | |
| 3014 | + CARD_STR2(L, p->zWikiTitle); | |
| 3015 | + ISA( CFTYPE_CLUSTER && p->nCChild>0 ){ | |
| 3016 | + CARD_LETTER(M); | |
| 3017 | + blob_append_char(b, '['); | |
| 3018 | + for( int i = 0; i < p->nCChild; ++i ){ | |
| 3019 | + if( i>0 ) blob_append_char(b, ','); | |
| 3020 | + blob_appendf(b, "%!j", p->azCChild[i]); | |
| 3021 | + } | |
| 3022 | + blob_append_char(b, ']'); | |
| 3023 | + } | |
| 3024 | + CARD_STR2(N, p->zMimetype); | |
| 3025 | + if( p->nParent ){ | |
| 3026 | + CARD_LETTER(P); | |
| 3027 | + blob_append_char(b, '['); | |
| 3028 | + for( i = 0; i < p->nParent; ++i ){ | |
| 3029 | + if( i>0 ) blob_append_char(b, ','); | |
| 3030 | + blob_appendf(b, "%!j", p->azParent[i]); | |
| 3031 | + } | |
| 3032 | + blob_append_char(b, ']'); | |
| 3033 | + } | |
| 3034 | + if( p->nCherrypick ){ | |
| 3035 | + CARD_LETTER(Q); | |
| 3036 | + blob_append_char(b, '['); | |
| 3037 | + for( i = 0; i < p->nCherrypick; ++i ){ | |
| 3038 | + if( i>0 ) blob_append_char(b, ','); | |
| 3039 | + blob_append_char(b, '{'); | |
| 3040 | + blob_appendf(b, "\"type\": \"%c\"", p->aCherrypick[i].zCPTarget[0]); | |
| 3041 | + KVP_STR(1, target, &p->aCherrypick[i].zCPTarget[1]); | |
| 3042 | + KVP_STR(1, base, p->aCherrypick[i].zCPBase); | |
| 3043 | + blob_append_char(b, '}'); | |
| 3044 | + } | |
| 3045 | + blob_append_char(b, ']'); | |
| 3046 | + } | |
| 2938 | 3047 | CARD_STR2(R, p->zRepoCksum); |
| 2939 | - blob_append_literal(pOut, "}"); | |
| 3048 | + if( p->nTag ){ | |
| 3049 | + CARD_LETTER(T); | |
| 3050 | + blob_append_char(b, '['); | |
| 3051 | + for( int i = 0; i < p->nTag; ++i ){ | |
| 3052 | + const char *zName = p->aTag[i].zName; | |
| 3053 | + if( i>0 ) blob_append_char(b, ','); | |
| 3054 | + blob_append_char(b, '{'); | |
| 3055 | + blob_appendf(b, "\"type\": \"%c\"", *zName); | |
| 3056 | + ++zName; | |
| 3057 | + KVP_STR(1, name, zName); | |
| 3058 | + KVP_STR(1, target, p->aTag[i].zUuid ? p->aTag[i].zUuid : "*") | |
| 3059 | + /* We could arguably resolve this to null. Per /chat | |
| 3060 | + discussion we don't want to resolve it to zUuid because | |
| 3061 | + that would effectively add information to the rendered | |
| 3062 | + manifest. */; | |
| 3063 | + KVP_STR(1, value, p->aTag[i].zValue); | |
| 3064 | + blob_append_char(b, '}'); | |
| 3065 | + } | |
| 3066 | + blob_append_char(b, ']'); | |
| 3067 | + } | |
| 3068 | + CARD_STR2(U, p->zUser); | |
| 3069 | + CARD_STR2(W, p->zWiki); | |
| 3070 | + fossil_free(zUuid); | |
| 3071 | + blob_append_literal(b, "}"); | |
| 3072 | +#undef CARD_FMT | |
| 3073 | +#undef CARD_LETTER | |
| 2940 | 3074 | #undef CARD_STR |
| 2941 | 3075 | #undef CARD_STR2 |
| 2942 | -#undef CARD_FMT | |
| 3076 | +#undef ISA | |
| 3077 | +#undef KVP_STR | |
| 3078 | +#undef STR_OR_NULL | |
| 2943 | 3079 | } |
| 2944 | 3080 | |
| 2945 | 3081 | /* |
| 2946 | 3082 | ** Convenience wrapper around artifact_to_json() which accepts any |
| 2947 | 3083 | ** artifact name which is legal for symbolic_name_to_rid(). On success |
| 2948 | 3084 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -2911,37 +2911,173 @@ | |
| 2911 | if( g.argc!=3 ) usage("RECORDID"); |
| 2912 | rid = name_to_rid(g.argv[2]); |
| 2913 | content_get(rid, &content); |
| 2914 | manifest_crosslink(rid, &content, MC_NONE); |
| 2915 | } |
| 2916 | |
| 2917 | /* |
| 2918 | ** Creates a JSON representation of p, appending it to pOut. |
| 2919 | */ |
| 2920 | void artifact_to_json(Manifest *p, Blob *pOut){ |
| 2921 | char * zTmp; |
| 2922 | blob_append_literal(pOut, "{"); |
| 2923 | blob_appendf(pOut, "\"rid\": %d", p->rid); |
| 2924 | zTmp = rid_to_uuid(p->rid); |
| 2925 | blob_appendf(pOut, ", \"uuid\": %!j", zTmp); |
| 2926 | fossil_free(zTmp); |
| 2927 | #define CARD_FMT(LETTER, FMT, VAL) \ |
| 2928 | blob_appendf(pOut, ",\"" #LETTER "\": " #FMT, VAL) |
| 2929 | #define CARD_STR(LETTER, VAL) \ |
| 2930 | assert( VAL ); CARD_FMT(LETTER, %!j, VAL) |
| 2931 | #define CARD_STR2(LETTER, VAL) \ |
| 2932 | if( VAL ) { CARD_FMT(LETTER, %!j, VAL); } |
| 2933 | |
| 2934 | CARD_STR2(B, p->zBaseline); |
| 2935 | CARD_STR2(C, p->zComment); |
| 2936 | CARD_FMT(D, %f, p->rDate); |
| 2937 | CARD_STR2(W, p->zWiki); |
| 2938 | CARD_STR2(R, p->zRepoCksum); |
| 2939 | blob_append_literal(pOut, "}"); |
| 2940 | #undef CARD_STR |
| 2941 | #undef CARD_STR2 |
| 2942 | #undef CARD_FMT |
| 2943 | } |
| 2944 | |
| 2945 | /* |
| 2946 | ** Convenience wrapper around artifact_to_json() which accepts any |
| 2947 | ** artifact name which is legal for symbolic_name_to_rid(). On success |
| 2948 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -2911,37 +2911,173 @@ | |
| 2911 | if( g.argc!=3 ) usage("RECORDID"); |
| 2912 | rid = name_to_rid(g.argv[2]); |
| 2913 | content_get(rid, &content); |
| 2914 | manifest_crosslink(rid, &content, MC_NONE); |
| 2915 | } |
| 2916 | |
| 2917 | /* |
| 2918 | ** For a given CATYPE_... value, returns a human-friendly name, or |
| 2919 | ** NULL if typeId is unknown or is CFTYPE_ANY. |
| 2920 | */ |
| 2921 | const char * artifact_type_to_name(int typeId){ |
| 2922 | switch(typeId){ |
| 2923 | case CFTYPE_MANIFEST: return "checkin"; |
| 2924 | case CFTYPE_CLUSTER: return "cluster"; |
| 2925 | case CFTYPE_CONTROL: return "control"; |
| 2926 | case CFTYPE_WIKI: return "wiki"; |
| 2927 | case CFTYPE_TICKET: return "ticket"; |
| 2928 | case CFTYPE_ATTACHMENT: return "attachment"; |
| 2929 | case CFTYPE_EVENT: return "event"; |
| 2930 | case CFTYPE_FORUM: return "forumpost"; |
| 2931 | } |
| 2932 | return NULL; |
| 2933 | } |
| 2934 | |
| 2935 | /* |
| 2936 | ** Creates a JSON representation of p, appending it to pOut. |
| 2937 | ** |
| 2938 | ** Pedantic note: this routine traverses p->aFile directly, rather than |
| 2939 | ** using manifest_file_next(), so that delta manifests are rendered as-is |
| 2940 | ** instead of having their derived files. If that policy is ever changed, |
| 2941 | ** p will need to be non-const. |
| 2942 | */ |
| 2943 | void artifact_to_json(Manifest const *p, Blob *b){ |
| 2944 | int i; |
| 2945 | char *zUuid; |
| 2946 | |
| 2947 | blob_append_literal(b, "{"); |
| 2948 | blob_appendf(b, "\"rid\": %d", p->rid); |
| 2949 | zUuid = rid_to_uuid(p->rid); |
| 2950 | blob_appendf(b, ", \"uuid\": %!j", zUuid); |
| 2951 | blob_appendf(b, ", \"type\": %!j", artifact_type_to_name(p->type)); |
| 2952 | #define ISA(TYPE) if( p->type==TYPE ) |
| 2953 | #define CARD_LETTER(LETTER) \ |
| 2954 | blob_append_literal(b, ",\"" #LETTER "\": ") |
| 2955 | #define CARD_STR(LETTER, VAL) \ |
| 2956 | assert( VAL ); CARD_LETTER(LETTER); blob_appendf(b, "%!j", VAL) |
| 2957 | #define CARD_STR2(LETTER, VAL) \ |
| 2958 | if( VAL ) { CARD_STR(LETTER, VAL); } (void)0 |
| 2959 | #define STR_OR_NULL(VAL) \ |
| 2960 | if( VAL ) blob_appendf(b, "%!j", VAL); \ |
| 2961 | else blob_append(b, "null", 4) |
| 2962 | #define KVP_STR(ADDCOMMA, KEY,VAL) \ |
| 2963 | if(ADDCOMMA) blob_append_char(b, ','); \ |
| 2964 | blob_appendf(b, "%!j: ", #KEY); \ |
| 2965 | STR_OR_NULL(VAL) |
| 2966 | |
| 2967 | /* Noting that only 1 (at most) of the A-card pieces will be non-NULL... */ |
| 2968 | ISA( CFTYPE_ATTACHMENT ){ |
| 2969 | CARD_LETTER(A); |
| 2970 | blob_append_char(b, '{'); |
| 2971 | KVP_STR(0, filename, p->zAttachName); |
| 2972 | KVP_STR(1, target, p->zAttachTarget); |
| 2973 | KVP_STR(1, source, p->zAttachSrc); |
| 2974 | blob_append_char(b, '}'); |
| 2975 | } |
| 2976 | CARD_STR2(B, p->zBaseline); |
| 2977 | CARD_STR2(C, p->zComment); |
| 2978 | CARD_LETTER(D); blob_appendf(b, "%f", p->rDate); |
| 2979 | ISA( CFTYPE_EVENT ){ |
| 2980 | blob_appendf(b, ", \"E\": {\"time\": %f, \"id\": %!j}", |
| 2981 | p->rEventDate, p->zEventId); |
| 2982 | } |
| 2983 | ISA( CFTYPE_MANIFEST ){ |
| 2984 | CARD_LETTER(F); |
| 2985 | blob_append_char(b, '['); |
| 2986 | for( i = 0; i < p->nFile; ++i ){ |
| 2987 | ManifestFile const * const pF = &p->aFile[i]; |
| 2988 | if( i>0 ) blob_append_char(b, ','); |
| 2989 | blob_append_char(b, '{'); |
| 2990 | KVP_STR(0, name, pF->zName); |
| 2991 | KVP_STR(1, uuid, pF->zUuid); |
| 2992 | KVP_STR(1, perm, pF->zPerm); |
| 2993 | KVP_STR(1, oldName, pF->zPrior); |
| 2994 | blob_append_char(b, '}'); |
| 2995 | } |
| 2996 | blob_append_char(b, ']'); |
| 2997 | } |
| 2998 | CARD_STR2(G, p->zThreadRoot); |
| 2999 | CARD_STR2(H, p->zThreadTitle); |
| 3000 | CARD_STR2(I, p->zInReplyTo); |
| 3001 | if( p->nField ){ |
| 3002 | CARD_LETTER(J); |
| 3003 | blob_append_char(b, '['); |
| 3004 | for( i = 0; i < p->nField; ++i ){ |
| 3005 | if( i>0 ) blob_append_char(b, ','); |
| 3006 | blob_append_char(b, '{'); |
| 3007 | KVP_STR(0, name, p->aField[i].zName); |
| 3008 | KVP_STR(1, value, p->aField[i].zValue); |
| 3009 | blob_append_char(b, '}'); |
| 3010 | } |
| 3011 | blob_append_char(b, ']'); |
| 3012 | } |
| 3013 | CARD_STR2(K, p->zTicketUuid); |
| 3014 | CARD_STR2(L, p->zWikiTitle); |
| 3015 | ISA( CFTYPE_CLUSTER && p->nCChild>0 ){ |
| 3016 | CARD_LETTER(M); |
| 3017 | blob_append_char(b, '['); |
| 3018 | for( int i = 0; i < p->nCChild; ++i ){ |
| 3019 | if( i>0 ) blob_append_char(b, ','); |
| 3020 | blob_appendf(b, "%!j", p->azCChild[i]); |
| 3021 | } |
| 3022 | blob_append_char(b, ']'); |
| 3023 | } |
| 3024 | CARD_STR2(N, p->zMimetype); |
| 3025 | if( p->nParent ){ |
| 3026 | CARD_LETTER(P); |
| 3027 | blob_append_char(b, '['); |
| 3028 | for( i = 0; i < p->nParent; ++i ){ |
| 3029 | if( i>0 ) blob_append_char(b, ','); |
| 3030 | blob_appendf(b, "%!j", p->azParent[i]); |
| 3031 | } |
| 3032 | blob_append_char(b, ']'); |
| 3033 | } |
| 3034 | if( p->nCherrypick ){ |
| 3035 | CARD_LETTER(Q); |
| 3036 | blob_append_char(b, '['); |
| 3037 | for( i = 0; i < p->nCherrypick; ++i ){ |
| 3038 | if( i>0 ) blob_append_char(b, ','); |
| 3039 | blob_append_char(b, '{'); |
| 3040 | blob_appendf(b, "\"type\": \"%c\"", p->aCherrypick[i].zCPTarget[0]); |
| 3041 | KVP_STR(1, target, &p->aCherrypick[i].zCPTarget[1]); |
| 3042 | KVP_STR(1, base, p->aCherrypick[i].zCPBase); |
| 3043 | blob_append_char(b, '}'); |
| 3044 | } |
| 3045 | blob_append_char(b, ']'); |
| 3046 | } |
| 3047 | CARD_STR2(R, p->zRepoCksum); |
| 3048 | if( p->nTag ){ |
| 3049 | CARD_LETTER(T); |
| 3050 | blob_append_char(b, '['); |
| 3051 | for( int i = 0; i < p->nTag; ++i ){ |
| 3052 | const char *zName = p->aTag[i].zName; |
| 3053 | if( i>0 ) blob_append_char(b, ','); |
| 3054 | blob_append_char(b, '{'); |
| 3055 | blob_appendf(b, "\"type\": \"%c\"", *zName); |
| 3056 | ++zName; |
| 3057 | KVP_STR(1, name, zName); |
| 3058 | KVP_STR(1, target, p->aTag[i].zUuid ? p->aTag[i].zUuid : "*") |
| 3059 | /* We could arguably resolve this to null. Per /chat |
| 3060 | discussion we don't want to resolve it to zUuid because |
| 3061 | that would effectively add information to the rendered |
| 3062 | manifest. */; |
| 3063 | KVP_STR(1, value, p->aTag[i].zValue); |
| 3064 | blob_append_char(b, '}'); |
| 3065 | } |
| 3066 | blob_append_char(b, ']'); |
| 3067 | } |
| 3068 | CARD_STR2(U, p->zUser); |
| 3069 | CARD_STR2(W, p->zWiki); |
| 3070 | fossil_free(zUuid); |
| 3071 | blob_append_literal(b, "}"); |
| 3072 | #undef CARD_FMT |
| 3073 | #undef CARD_LETTER |
| 3074 | #undef CARD_STR |
| 3075 | #undef CARD_STR2 |
| 3076 | #undef ISA |
| 3077 | #undef KVP_STR |
| 3078 | #undef STR_OR_NULL |
| 3079 | } |
| 3080 | |
| 3081 | /* |
| 3082 | ** Convenience wrapper around artifact_to_json() which accepts any |
| 3083 | ** artifact name which is legal for symbolic_name_to_rid(). On success |
| 3084 |