/* ** If any files are associated with the given rid, a JSON array ** containing information about them is returned (and is owned by the ** caller). If no files are associated with it then NULL is returned. ** ** flags may optionally be a bitmask of json_get_changed_files flags, ** or 0 for defaults. */ cson_value * json_get_changed_files(int rid, int flags){ cson_value * rowsV = NULL; cson_array * rows = NULL; Stmt q = empty_Stmt; db_prepare(&q, "SELECT (pid==0) AS isnew," " (fid==0) AS isdel," " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," " blob.uuid as uuid," " (SELECT uuid FROM blob WHERE rid=pid) as parent," " blob.size as size" " FROM mlink, blob" " WHERE mid=%d AND pid!=fid" " AND blob.rid=fid AND NOT mlink.isaux" " ORDER BY name /*sort*/", rid ); while( (SQLITE_ROW == db_step(&q)) ){ cson_value * rowV = cson_value_new_object(); cson_object * row = cson_value_get_object(rowV); int const isNew = db_column_int(&q,0); int const isDel = db_column_int(&q,1); char * zDownload = NULL; if(!rowsV){ rowsV = cson_value_new_array(); rows = cson_value_get_array(rowsV); } cson_array_append( rows, rowV ); cson_object_set(row, "name", json_new_string(db_column_text(&q,2))); cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3))); if(!isNew && (flags & json_get_changed_files_ELIDE_PARENT)){ cson_object_set(row, "parent", json_new_string(db_column_text(&q,4))); } cson_object_set(row, "size", json_new_int(db_column_int(&q,5))); cson_object_set(row, "state", json_new_string(json_artifact_status_to_string(isNew,isDel))); zDownload = mprintf("/raw/%s?name=%s", /* reminder: g.zBaseURL is of course not set for CLI mode. */ db_column_text(&q,2), db_column_text(&q,3)); cson_object_set(row, "downloadPath", json_new_string(zDownload)); free(zDownload); } db_finalize(&q); return rowsV; }
cson_value * json_artifact_file(cson_object * zParent, int rid){ cson_object * pay = NULL; Stmt q = empty_Stmt; cson_array * checkin_arr = NULL; char contentFormat; i64 contentSize = -1; char * parentUuid; if( ! g.perm.Read ){ json_set_err(FSL_JSON_E_DENIED, "Requires 'o' privileges."); return NULL; } pay = zParent; contentFormat = json_artifact_get_content_format_flag(); if( 0 != contentFormat ){ Blob content = empty_blob; const char *zMime; char const * zFormat = (contentFormat<1) ? "raw" : "html"; content_get(rid, &content); zMime = mimetype_from_content(&content); cson_object_set(zParent, "contentType", json_new_string(zMime ? zMime : "text/plain")); if(!zMime){/* text/plain */ if(0 < blob_size(&content)){ if( 0 < contentFormat ){/*HTML-size it*/ Blob html = empty_blob; wiki_convert(&content, &html, 0); assert( blob_size(&content) < blob_size(&html) ); blob_swap( &html, &content ); assert( blob_size(&content) > blob_size(&html) ); blob_reset( &html ); }/*else as-is*/ } cson_object_set(zParent, "content", cson_value_new_string(blob_str(&content), (unsigned int)blob_size(&content))); }/*else binary: ignore*/ contentSize = blob_size(&content); cson_object_set(zParent, "contentSize", json_new_int(contentSize) ); cson_object_set(zParent, "contentFormat", json_new_string(zFormat) ); blob_reset(&content); } contentSize = db_int64(-1, "SELECT size FROM blob WHERE rid=%d", rid); assert( -1 < contentSize ); cson_object_set(zParent, "size", json_new_int(contentSize) ); parentUuid = db_text(NULL, "SELECT DISTINCT p.uuid " "FROM blob p, blob f, mlink m " "WHERE m.pid=p.rid " "AND m.fid=f.rid " "AND f.rid=%d", rid ); if(parentUuid){ cson_object_set( zParent, "parent", json_new_string(parentUuid) ); fossil_free(parentUuid); } /* Find checkins associated with this file... */ db_prepare(&q, "SELECT filename.name AS name, " " (mlink.pid==0) AS isNew," " (mlink.fid==0) AS isDel," " cast(strftime('%%s',event.mtime) as int) AS timestamp," " coalesce(event.ecomment,event.comment) as comment," " coalesce(event.euser,event.user) as user," #if 0 " a.size AS size," /* same for all checkins. */ #endif " b.uuid as checkin, " #if 0 " mlink.mperm as mperm," #endif " coalesce((SELECT value FROM tagxref" " WHERE tagid=%d AND tagtype>0 AND " " rid=mlink.mid),'trunk') as branch" " FROM mlink, filename, event, blob a, blob b" " WHERE filename.fnid=mlink.fnid" " AND event.objid=mlink.mid" " AND a.rid=mlink.fid" " AND b.rid=mlink.mid" " AND mlink.fid=%d" " ORDER BY filename.name, event.mtime", TAG_BRANCH, rid ); /* TODO: add a "state" flag for the file in each checkin, e.g. "modified", "new", "deleted". */ checkin_arr = cson_new_array(); cson_object_set(pay, "checkins", cson_array_value(checkin_arr)); while( (SQLITE_ROW==db_step(&q) ) ){ cson_object * row = cson_value_get_object(cson_sqlite3_row_to_object(q.pStmt)); /* FIXME: move this isNew/isDel stuff into an SQL CASE statement. */ char const isNew = cson_value_get_bool(cson_object_get(row,"isNew")); char const isDel = cson_value_get_bool(cson_object_get(row,"isDel")); cson_object_set(row, "isNew", NULL); cson_object_set(row, "isDel", NULL); cson_object_set(row, "state", json_new_string(json_artifact_status_to_string(isNew, isDel))); cson_array_append( checkin_arr, cson_object_value(row) ); } db_finalize(&q); return cson_object_value(pay); }