1251881Speter/* 2251881Speter * log.c : Functions for logging Subversion operations 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter 27251881Speter#include <stdarg.h> 28251881Speter 29251881Speter#define APR_WANT_STRFUNC 30251881Speter#include <apr_want.h> 31251881Speter#include <apr_strings.h> 32251881Speter 33251881Speter#include "svn_types.h" 34251881Speter#include "svn_error.h" 35251881Speter#include "svn_mergeinfo.h" 36251881Speter#include "svn_path.h" 37251881Speter#include "svn_pools.h" 38251881Speter#include "svn_string.h" 39251881Speter 40251881Speter#include "private/svn_log.h" 41251881Speter 42251881Speter 43251881Speterstatic const char * 44251881Speterlog_depth(svn_depth_t depth, apr_pool_t *pool) 45251881Speter{ 46251881Speter if (depth == svn_depth_unknown) 47251881Speter return ""; 48251881Speter return apr_pstrcat(pool, " depth=", svn_depth_to_word(depth), (char *)NULL); 49251881Speter} 50251881Speter 51251881Speterstatic const char * 52251881Speterlog_include_merged_revisions(svn_boolean_t include_merged_revisions) 53251881Speter{ 54251881Speter if (include_merged_revisions) 55251881Speter return " include-merged-revisions"; 56251881Speter return ""; 57251881Speter} 58251881Speter 59251881Speter 60251881Speterconst char * 61251881Spetersvn_log__reparent(const char *path, apr_pool_t *pool) 62251881Speter{ 63251881Speter return apr_psprintf(pool, "reparent %s", svn_path_uri_encode(path, pool)); 64251881Speter 65251881Speter} 66251881Speter 67251881Speterconst char * 68251881Spetersvn_log__change_rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool) 69251881Speter{ 70251881Speter return apr_psprintf(pool, "change-rev-prop r%ld %s", rev, 71251881Speter svn_path_uri_encode(name, pool)); 72251881Speter} 73251881Speter 74251881Speterconst char * 75251881Spetersvn_log__rev_proplist(svn_revnum_t rev, apr_pool_t *pool) 76251881Speter{ 77251881Speter return apr_psprintf(pool, "rev-proplist r%ld", rev); 78251881Speter} 79251881Speter 80251881Speterconst char * 81251881Spetersvn_log__rev_prop(svn_revnum_t rev, const char *name, apr_pool_t *pool) 82251881Speter{ 83251881Speter return apr_psprintf(pool, "rev-prop r%ld %s", rev, 84251881Speter svn_path_uri_encode(name, pool)); 85251881Speter} 86251881Speter 87251881Speterconst char * 88251881Spetersvn_log__commit(svn_revnum_t rev, apr_pool_t *pool) 89251881Speter{ 90251881Speter return apr_psprintf(pool, "commit r%ld", rev); 91251881Speter} 92251881Speter 93251881Speterconst char * 94251881Spetersvn_log__get_file(const char *path, svn_revnum_t rev, 95251881Speter svn_boolean_t want_contents, svn_boolean_t want_props, 96251881Speter apr_pool_t *pool) 97251881Speter{ 98251881Speter return apr_psprintf(pool, "get-file %s r%ld%s%s", 99251881Speter svn_path_uri_encode(path, pool), rev, 100251881Speter want_contents ? " text" : "", 101251881Speter want_props ? " props" : ""); 102251881Speter} 103251881Speter 104251881Speterconst char * 105251881Spetersvn_log__get_dir(const char *path, svn_revnum_t rev, 106251881Speter svn_boolean_t want_contents, svn_boolean_t want_props, 107251881Speter apr_uint64_t dirent_fields, 108251881Speter apr_pool_t *pool) 109251881Speter{ 110251881Speter return apr_psprintf(pool, "get-dir %s r%ld%s%s", 111251881Speter svn_path_uri_encode(path, pool), rev, 112251881Speter want_contents ? " text" : "", 113251881Speter want_props ? " props" : ""); 114251881Speter} 115251881Speter 116251881Speterconst char * 117251881Spetersvn_log__get_mergeinfo(const apr_array_header_t *paths, 118251881Speter svn_mergeinfo_inheritance_t inherit, 119251881Speter svn_boolean_t include_descendants, 120251881Speter apr_pool_t *pool) 121251881Speter{ 122251881Speter int i; 123251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 124251881Speter svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool); 125251881Speter 126251881Speter for (i = 0; i < paths->nelts; i++) 127251881Speter { 128251881Speter const char *path = APR_ARRAY_IDX(paths, i, const char *); 129251881Speter svn_pool_clear(iterpool); 130251881Speter if (i != 0) 131251881Speter svn_stringbuf_appendcstr(space_separated_paths, " "); 132251881Speter svn_stringbuf_appendcstr(space_separated_paths, 133251881Speter svn_path_uri_encode(path, iterpool)); 134251881Speter } 135251881Speter svn_pool_destroy(iterpool); 136251881Speter 137251881Speter return apr_psprintf(pool, "get-mergeinfo (%s) %s%s", 138251881Speter space_separated_paths->data, 139251881Speter svn_inheritance_to_word(inherit), 140251881Speter include_descendants ? " include-descendants" : ""); 141251881Speter} 142251881Speter 143251881Speterconst char * 144251881Spetersvn_log__checkout(const char *path, svn_revnum_t rev, svn_depth_t depth, 145251881Speter apr_pool_t *pool) 146251881Speter{ 147251881Speter return apr_psprintf(pool, "checkout-or-export %s r%ld%s", 148251881Speter svn_path_uri_encode(path, pool), rev, 149251881Speter log_depth(depth, pool)); 150251881Speter} 151251881Speter 152251881Speterconst char * 153251881Spetersvn_log__update(const char *path, svn_revnum_t rev, svn_depth_t depth, 154251881Speter svn_boolean_t send_copyfrom_args, 155251881Speter apr_pool_t *pool) 156251881Speter{ 157251881Speter return apr_psprintf(pool, "update %s r%ld%s%s", 158251881Speter svn_path_uri_encode(path, pool), rev, 159251881Speter log_depth(depth, pool), 160251881Speter (send_copyfrom_args 161251881Speter ? " send-copyfrom-args" 162251881Speter : "")); 163251881Speter} 164251881Speter 165251881Speterconst char * 166251881Spetersvn_log__switch(const char *path, const char *dst_path, svn_revnum_t revnum, 167251881Speter svn_depth_t depth, apr_pool_t *pool) 168251881Speter{ 169251881Speter return apr_psprintf(pool, "switch %s %s@%ld%s", 170251881Speter svn_path_uri_encode(path, pool), 171251881Speter svn_path_uri_encode(dst_path, pool), revnum, 172251881Speter log_depth(depth, pool)); 173251881Speter} 174251881Speter 175251881Speterconst char * 176251881Spetersvn_log__status(const char *path, svn_revnum_t rev, svn_depth_t depth, 177251881Speter apr_pool_t *pool) 178251881Speter{ 179251881Speter return apr_psprintf(pool, "status %s r%ld%s", 180251881Speter svn_path_uri_encode(path, pool), rev, 181251881Speter log_depth(depth, pool)); 182251881Speter} 183251881Speter 184251881Speterconst char * 185251881Spetersvn_log__diff(const char *path, svn_revnum_t from_revnum, 186251881Speter const char *dst_path, svn_revnum_t revnum, 187251881Speter svn_depth_t depth, svn_boolean_t ignore_ancestry, 188251881Speter apr_pool_t *pool) 189251881Speter{ 190251881Speter const char *log_ignore_ancestry = (ignore_ancestry 191251881Speter ? " ignore-ancestry" 192251881Speter : ""); 193251881Speter if (strcmp(path, dst_path) == 0) 194251881Speter return apr_psprintf(pool, "diff %s r%ld:%ld%s%s", 195251881Speter svn_path_uri_encode(path, pool), from_revnum, revnum, 196251881Speter log_depth(depth, pool), log_ignore_ancestry); 197251881Speter return apr_psprintf(pool, "diff %s@%ld %s@%ld%s%s", 198251881Speter svn_path_uri_encode(path, pool), from_revnum, 199251881Speter svn_path_uri_encode(dst_path, pool), revnum, 200251881Speter log_depth(depth, pool), log_ignore_ancestry); 201251881Speter} 202251881Speter 203251881Speterconst char * 204251881Spetersvn_log__log(const apr_array_header_t *paths, 205251881Speter svn_revnum_t start, svn_revnum_t end, 206251881Speter int limit, svn_boolean_t discover_changed_paths, 207251881Speter svn_boolean_t strict_node_history, 208251881Speter svn_boolean_t include_merged_revisions, 209251881Speter const apr_array_header_t *revprops, apr_pool_t *pool) 210251881Speter{ 211251881Speter int i; 212251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 213251881Speter svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool); 214251881Speter svn_stringbuf_t *options = svn_stringbuf_create_empty(pool); 215251881Speter 216251881Speter for (i = 0; i < paths->nelts; i++) 217251881Speter { 218251881Speter const char *path = APR_ARRAY_IDX(paths, i, const char *); 219251881Speter svn_pool_clear(iterpool); 220251881Speter if (i != 0) 221251881Speter svn_stringbuf_appendcstr(space_separated_paths, " "); 222251881Speter svn_stringbuf_appendcstr(space_separated_paths, 223251881Speter svn_path_uri_encode(path, iterpool)); 224251881Speter } 225251881Speter 226251881Speter if (limit) 227251881Speter { 228251881Speter const char *tmp = apr_psprintf(pool, " limit=%d", limit); 229251881Speter svn_stringbuf_appendcstr(options, tmp); 230251881Speter } 231251881Speter if (discover_changed_paths) 232251881Speter svn_stringbuf_appendcstr(options, " discover-changed-paths"); 233251881Speter if (strict_node_history) 234251881Speter svn_stringbuf_appendcstr(options, " strict"); 235251881Speter if (include_merged_revisions) 236251881Speter svn_stringbuf_appendcstr(options, 237251881Speter log_include_merged_revisions(include_merged_revisions)); 238251881Speter if (revprops == NULL) 239251881Speter svn_stringbuf_appendcstr(options, " revprops=all"); 240251881Speter else if (revprops->nelts > 0) 241251881Speter { 242251881Speter svn_stringbuf_appendcstr(options, " revprops=("); 243251881Speter for (i = 0; i < revprops->nelts; i++) 244251881Speter { 245251881Speter const char *name = APR_ARRAY_IDX(revprops, i, const char *); 246251881Speter svn_pool_clear(iterpool); 247251881Speter if (i != 0) 248251881Speter svn_stringbuf_appendcstr(options, " "); 249251881Speter svn_stringbuf_appendcstr(options, svn_path_uri_encode(name, 250251881Speter iterpool)); 251251881Speter } 252251881Speter svn_stringbuf_appendcstr(options, ")"); 253251881Speter } 254251881Speter svn_pool_destroy(iterpool); 255251881Speter return apr_psprintf(pool, "log (%s) r%ld:%ld%s", 256251881Speter space_separated_paths->data, start, end, 257251881Speter options->data); 258251881Speter} 259251881Speter 260251881Speterconst char * 261251881Spetersvn_log__get_locations(const char *path, svn_revnum_t peg_revision, 262251881Speter const apr_array_header_t *location_revisions, 263251881Speter apr_pool_t *pool) 264251881Speter{ 265251881Speter const svn_revnum_t *revision_ptr, *revision_ptr_start, *revision_ptr_end; 266251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 267251881Speter svn_stringbuf_t *space_separated_revnums = svn_stringbuf_create_empty(pool); 268251881Speter 269251881Speter revision_ptr_start = (const svn_revnum_t *)location_revisions->elts; 270251881Speter revision_ptr = revision_ptr_start; 271251881Speter revision_ptr_end = revision_ptr + location_revisions->nelts; 272251881Speter while (revision_ptr < revision_ptr_end) 273251881Speter { 274251881Speter svn_pool_clear(iterpool); 275251881Speter if (revision_ptr != revision_ptr_start) 276251881Speter svn_stringbuf_appendcstr(space_separated_revnums, " "); 277251881Speter svn_stringbuf_appendcstr(space_separated_revnums, 278251881Speter apr_psprintf(iterpool, "%ld", *revision_ptr)); 279251881Speter ++revision_ptr; 280251881Speter } 281251881Speter svn_pool_destroy(iterpool); 282251881Speter 283251881Speter return apr_psprintf(pool, "get-locations %s@%ld (%s)", 284251881Speter svn_path_uri_encode(path, pool), 285251881Speter peg_revision, space_separated_revnums->data); 286251881Speter} 287251881Speter 288251881Speterconst char * 289251881Spetersvn_log__get_location_segments(const char *path, svn_revnum_t peg_revision, 290251881Speter svn_revnum_t start, svn_revnum_t end, 291251881Speter apr_pool_t *pool) 292251881Speter{ 293251881Speter return apr_psprintf(pool, "get-location-segments %s@%ld r%ld:%ld", 294251881Speter svn_path_uri_encode(path, pool), 295251881Speter peg_revision, start, end); 296251881Speter} 297251881Speter 298251881Speterconst char * 299251881Spetersvn_log__get_file_revs(const char *path, svn_revnum_t start, svn_revnum_t end, 300251881Speter svn_boolean_t include_merged_revisions, 301251881Speter apr_pool_t *pool) 302251881Speter{ 303251881Speter return apr_psprintf(pool, "get-file-revs %s r%ld:%ld%s", 304251881Speter svn_path_uri_encode(path, pool), start, end, 305251881Speter log_include_merged_revisions(include_merged_revisions)); 306251881Speter} 307251881Speter 308251881Speterconst char * 309251881Spetersvn_log__lock(const apr_array_header_t *paths, 310251881Speter svn_boolean_t steal, apr_pool_t *pool) 311251881Speter{ 312251881Speter int i; 313251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 314251881Speter svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool); 315251881Speter 316251881Speter for (i = 0; i < paths->nelts; i++) 317251881Speter { 318251881Speter const char *path = APR_ARRAY_IDX(paths, i, const char *); 319251881Speter svn_pool_clear(iterpool); 320251881Speter if (i != 0) 321251881Speter svn_stringbuf_appendcstr(space_separated_paths, " "); 322251881Speter svn_stringbuf_appendcstr(space_separated_paths, 323251881Speter svn_path_uri_encode(path, iterpool)); 324251881Speter } 325251881Speter svn_pool_destroy(iterpool); 326251881Speter 327251881Speter return apr_psprintf(pool, "lock (%s)%s", space_separated_paths->data, 328251881Speter steal ? " steal" : ""); 329251881Speter} 330251881Speter 331251881Speterconst char * 332251881Spetersvn_log__unlock(const apr_array_header_t *paths, 333251881Speter svn_boolean_t break_lock, apr_pool_t *pool) 334251881Speter{ 335251881Speter int i; 336251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 337251881Speter svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool); 338251881Speter 339251881Speter for (i = 0; i < paths->nelts; i++) 340251881Speter { 341251881Speter const char *path = APR_ARRAY_IDX(paths, i, const char *); 342251881Speter svn_pool_clear(iterpool); 343251881Speter if (i != 0) 344251881Speter svn_stringbuf_appendcstr(space_separated_paths, " "); 345251881Speter svn_stringbuf_appendcstr(space_separated_paths, 346251881Speter svn_path_uri_encode(path, iterpool)); 347251881Speter } 348251881Speter svn_pool_destroy(iterpool); 349251881Speter 350251881Speter return apr_psprintf(pool, "unlock (%s)%s", space_separated_paths->data, 351251881Speter break_lock ? " break" : ""); 352251881Speter} 353251881Speter 354251881Speterconst char * 355251881Spetersvn_log__lock_one_path(const char *path, svn_boolean_t steal, 356251881Speter apr_pool_t *pool) 357251881Speter{ 358251881Speter apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(path)); 359251881Speter APR_ARRAY_PUSH(paths, const char *) = path; 360251881Speter return svn_log__lock(paths, steal, pool); 361251881Speter} 362251881Speter 363251881Speterconst char * 364251881Spetersvn_log__unlock_one_path(const char *path, svn_boolean_t break_lock, 365251881Speter apr_pool_t *pool) 366251881Speter{ 367251881Speter apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(path)); 368251881Speter APR_ARRAY_PUSH(paths, const char *) = path; 369251881Speter return svn_log__unlock(paths, break_lock, pool); 370251881Speter} 371251881Speter 372251881Speterconst char * 373251881Spetersvn_log__replay(const char *path, svn_revnum_t rev, apr_pool_t *pool) 374251881Speter{ 375251881Speter const char *log_path; 376251881Speter 377251881Speter if (path && path[0] != '\0') 378251881Speter log_path = svn_path_uri_encode(path, pool); 379251881Speter else 380251881Speter log_path = "/"; 381251881Speter return apr_psprintf(pool, "replay %s r%ld", log_path, rev); 382251881Speter} 383251881Speter 384251881Speterconst char * 385251881Spetersvn_log__get_inherited_props(const char *path, 386251881Speter svn_revnum_t rev, 387251881Speter apr_pool_t *pool) 388251881Speter{ 389251881Speter const char *log_path; 390251881Speter 391251881Speter if (path && path[0] != '\0') 392251881Speter log_path = svn_path_uri_encode(path, pool); 393251881Speter else 394251881Speter log_path = "/"; 395251881Speter return apr_psprintf(pool, "get-inherited-props %s r%ld", log_path, rev); 396251881Speter} 397