1251881Speter/* 2251881Speter * checkout-cmd.c -- Subversion checkout command 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 28251881Speter/*** Includes. ***/ 29251881Speter 30251881Speter#include "svn_client.h" 31251881Speter#include "svn_dirent_uri.h" 32251881Speter#include "svn_path.h" 33251881Speter#include "svn_error.h" 34251881Speter#include "svn_pools.h" 35251881Speter#include "cl.h" 36251881Speter 37251881Speter#include "svn_private_config.h" 38251881Speter 39251881Speter 40251881Speter/*** Code. ***/ 41251881Speter 42251881Speter/* 43251881Speter This is what it does 44251881Speter 45251881Speter - case 1: one URL 46251881Speter $ svn co http://host/repos/module 47251881Speter checkout into ./module/ 48251881Speter 49251881Speter - case 2: one URL and explicit path 50251881Speter $ svn co http://host/repos/module path 51251881Speter checkout into ./path/ 52251881Speter 53251881Speter - case 3: multiple URLs 54251881Speter $ svn co http://host1/repos1/module1 http://host2/repos2/module2 55251881Speter checkout into ./module1/ and ./module2/ 56251881Speter 57251881Speter - case 4: multiple URLs and explicit path 58251881Speter $ svn co http://host1/repos1/module1 http://host2/repos2/module2 path 59251881Speter checkout into ./path/module1/ and ./path/module2/ 60251881Speter 61251881Speter Is this the same as CVS? Does it matter if it is not? 62251881Speter*/ 63251881Speter 64251881Speter 65251881Speter/* This implements the `svn_opt_subcommand_t' interface. */ 66251881Spetersvn_error_t * 67251881Spetersvn_cl__checkout(apr_getopt_t *os, 68251881Speter void *baton, 69251881Speter apr_pool_t *pool) 70251881Speter{ 71251881Speter svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; 72251881Speter svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; 73251881Speter apr_pool_t *subpool; 74251881Speter apr_array_header_t *targets; 75299742Sdim struct svn_cl__check_externals_failed_notify_baton nwb; 76251881Speter const char *last_target, *local_dir; 77251881Speter int i; 78251881Speter 79251881Speter SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, 80251881Speter opt_state->targets, 81251881Speter ctx, FALSE, pool)); 82251881Speter 83251881Speter if (! targets->nelts) 84251881Speter return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, NULL); 85251881Speter 86251881Speter /* Determine LOCAL_DIR (case 1: URL basename; 2,4: specified; 3: "") 87251881Speter * and leave TARGETS holding just the source URLs. */ 88251881Speter last_target = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *); 89251881Speter if (svn_path_is_url(last_target)) 90251881Speter { 91251881Speter if (targets->nelts == 1) 92251881Speter { 93251881Speter svn_opt_revision_t pegrev; 94251881Speter 95251881Speter /* Use the URL basename, discarding any peg revision. */ 96251881Speter SVN_ERR(svn_opt_parse_path(&pegrev, &local_dir, last_target, pool)); 97251881Speter local_dir = svn_uri_basename(local_dir, pool); 98251881Speter } 99251881Speter else 100251881Speter { 101251881Speter local_dir = ""; 102251881Speter } 103251881Speter } 104251881Speter else 105251881Speter { 106251881Speter if (targets->nelts == 1) 107251881Speter /* What? They gave us one target, and it wasn't a URL. */ 108251881Speter return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, NULL); 109251881Speter 110251881Speter apr_array_pop(targets); 111251881Speter local_dir = last_target; 112251881Speter } 113251881Speter 114251881Speter if (! opt_state->quiet) 115251881Speter SVN_ERR(svn_cl__notifier_mark_checkout(ctx->notify_baton2)); 116251881Speter 117299742Sdim nwb.wrapped_func = ctx->notify_func2; 118299742Sdim nwb.wrapped_baton = ctx->notify_baton2; 119299742Sdim nwb.had_externals_error = FALSE; 120299742Sdim ctx->notify_func2 = svn_cl__check_externals_failed_notify_wrapper; 121299742Sdim ctx->notify_baton2 = &nwb; 122299742Sdim 123251881Speter subpool = svn_pool_create(pool); 124251881Speter for (i = 0; i < targets->nelts; ++i) 125251881Speter { 126251881Speter const char *repos_url = APR_ARRAY_IDX(targets, i, const char *); 127251881Speter const char *target_dir; 128251881Speter const char *true_url; 129251881Speter svn_opt_revision_t revision = opt_state->start_revision; 130251881Speter svn_opt_revision_t peg_revision; 131251881Speter 132251881Speter svn_pool_clear(subpool); 133251881Speter 134251881Speter SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); 135251881Speter 136251881Speter /* Validate the REPOS_URL */ 137251881Speter if (! svn_path_is_url(repos_url)) 138251881Speter return svn_error_createf 139251881Speter (SVN_ERR_BAD_URL, NULL, 140251881Speter _("'%s' does not appear to be a URL"), repos_url); 141251881Speter 142251881Speter /* Get a possible peg revision. */ 143251881Speter SVN_ERR(svn_opt_parse_path(&peg_revision, &true_url, repos_url, 144251881Speter subpool)); 145251881Speter 146251881Speter /* Use sub-directory of destination if checking-out multiple URLs */ 147251881Speter if (targets->nelts == 1) 148251881Speter { 149251881Speter target_dir = local_dir; 150251881Speter } 151251881Speter else 152251881Speter { 153251881Speter target_dir = svn_dirent_join(local_dir, 154251881Speter svn_uri_basename(true_url, subpool), 155251881Speter subpool); 156251881Speter } 157251881Speter 158251881Speter /* Checkout doesn't accept an unspecified revision, so default to 159251881Speter the peg revision, or to HEAD if there wasn't a peg. */ 160251881Speter if (revision.kind == svn_opt_revision_unspecified) 161251881Speter { 162251881Speter if (peg_revision.kind != svn_opt_revision_unspecified) 163251881Speter revision = peg_revision; 164251881Speter else 165251881Speter revision.kind = svn_opt_revision_head; 166251881Speter } 167251881Speter 168251881Speter SVN_ERR(svn_client_checkout3 169251881Speter (NULL, true_url, target_dir, 170251881Speter &peg_revision, 171251881Speter &revision, 172251881Speter opt_state->depth, 173251881Speter opt_state->ignore_externals, 174251881Speter opt_state->force, 175251881Speter ctx, subpool)); 176251881Speter } 177251881Speter svn_pool_destroy(subpool); 178251881Speter 179299742Sdim if (nwb.had_externals_error) 180299742Sdim return svn_error_create(SVN_ERR_CL_ERROR_PROCESSING_EXTERNALS, NULL, 181299742Sdim _("Failure occurred processing one or " 182299742Sdim "more externals definitions")); 183299742Sdim 184251881Speter return SVN_NO_ERROR; 185251881Speter} 186