~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_client/import.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
#include "svn_props.h"
48
48
 
49
49
#include "client.h"
 
50
#include "private/svn_ra_private.h"
 
51
#include "private/svn_sorts_private.h"
50
52
#include "private/svn_subr_private.h"
51
 
#include "private/svn_ra_private.h"
52
53
#include "private/svn_magic.h"
53
54
 
54
55
#include "svn_private_config.h"
55
56
 
56
 
/* Import context baton.
57
 
 
58
 
   ### TODO:  Add the following items to this baton:
59
 
      /` import editor/baton. `/
60
 
      const svn_delta_editor_t *editor;
61
 
      void *edit_baton;
62
 
 
63
 
      /` Client context baton `/
64
 
      svn_client_ctx_t `ctx;
65
 
 
66
 
      /` Paths (keys) excluded from the import (values ignored) `/
67
 
      apr_hash_t *excludes;
68
 
*/
 
57
/* Import context baton. */
 
58
 
69
59
typedef struct import_ctx_t
70
60
{
71
61
  /* Whether any changes were made to the repository */
238
228
    {
239
229
      for (hi = apr_hash_first(pool, properties); hi; hi = apr_hash_next(hi))
240
230
        {
241
 
          const char *pname = svn__apr_hash_index_key(hi);
242
 
          const svn_string_t *pval = svn__apr_hash_index_val(hi);
 
231
          const char *pname = apr_hash_this_key(hi);
 
232
          const svn_string_t *pval = apr_hash_this_val(hi);
243
233
 
244
234
          SVN_ERR(editor->change_file_prop(file_baton, pname, pval, pool));
245
235
        }
255
245
      notify->content_state = notify->prop_state
256
246
        = svn_wc_notify_state_inapplicable;
257
247
      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
258
 
      (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
 
248
      ctx->notify_func2(ctx->notify_baton2, notify, pool);
259
249
    }
260
250
 
261
251
  /* If this is a special file, we need to set the svn:special
279
269
  text_checksum =
280
270
    svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool);
281
271
 
282
 
  return editor->close_file(file_baton, text_checksum, pool);
 
272
  return svn_error_trace(editor->close_file(file_baton, text_checksum, pool));
283
273
}
284
274
 
285
275
 
312
302
 
313
303
  for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
314
304
    {
315
 
      const char *base_name = svn__apr_hash_index_key(hi);
316
 
      const svn_io_dirent2_t *dirent = svn__apr_hash_index_val(hi);
 
305
      const char *base_name = apr_hash_this_key(hi);
 
306
      const svn_io_dirent2_t *dirent = apr_hash_this_val(hi);
317
307
      const char *local_abspath;
318
308
 
319
309
      svn_pool_clear(iterpool);
338
328
              notify->content_state = notify->prop_state
339
329
                = svn_wc_notify_state_inapplicable;
340
330
              notify->lock_state = svn_wc_notify_lock_state_inapplicable;
341
 
              (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
 
331
              ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
342
332
            }
343
333
 
344
334
          svn_hash_sets(dirents, base_name, NULL);
480
470
                  notify->content_state = notify->prop_state
481
471
                    = svn_wc_notify_state_inapplicable;
482
472
                  notify->lock_state = svn_wc_notify_lock_state_inapplicable;
483
 
                  (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
 
473
                  ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
484
474
                }
485
475
            }
486
476
          else
569
559
        notify->content_state = notify->prop_state
570
560
          = svn_wc_notify_state_inapplicable;
571
561
        notify->lock_state = svn_wc_notify_lock_state_inapplicable;
572
 
        (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
 
562
        ctx->notify_func2(ctx->notify_baton2, notify, pool);
573
563
      }
574
564
  }
575
565
 
590
580
/* Recursively import PATH to a repository using EDITOR and
591
581
 * EDIT_BATON.  PATH can be a file or directory.
592
582
 *
 
583
 * Sets *UPDATED_REPOSITORY to TRUE when the repository was modified by
 
584
 * a successfull commit, otherwise to FALSE.
 
585
 *
593
586
 * DEPTH is the depth at which to import PATH; it behaves as for
594
587
 * svn_client_import4().
595
588
 *
 
589
 * BASE_REV is the revision to use for the root of the commit. We
 
590
 * checked the preconditions against this revision.
 
591
 *
596
592
 * NEW_ENTRIES is an ordered array of path components that must be
597
593
 * created in the repository (where the ordering direction is
598
594
 * parent-to-child).  If PATH is a directory, NEW_ENTRIES may be empty
636
632
 * not necessarily the root.)
637
633
 */
638
634
static svn_error_t *
639
 
import(const char *local_abspath,
 
635
import(svn_boolean_t *updated_repository,
 
636
       const char *local_abspath,
 
637
       const char *url,
640
638
       const apr_array_header_t *new_entries,
641
639
       const svn_delta_editor_t *editor,
642
640
       void *edit_baton,
643
641
       svn_depth_t depth,
 
642
       svn_revnum_t base_rev,
644
643
       apr_hash_t *excludes,
645
644
       apr_hash_t *autoprops,
646
645
       apr_array_header_t *local_ignores,
656
655
  void *root_baton;
657
656
  apr_array_header_t *batons = NULL;
658
657
  const char *edit_path = "";
659
 
  import_ctx_t *import_ctx = apr_pcalloc(pool, sizeof(*import_ctx));
 
658
  import_ctx_t import_ctx = { FALSE };
660
659
  const svn_io_dirent2_t *dirent;
661
660
 
662
 
  import_ctx->autoprops = autoprops;
663
 
  svn_magic__init(&import_ctx->magic_cookie, pool);
664
 
 
665
 
  /* Get a root dir baton.  We pass an invalid revnum to open_root
666
 
     to mean "base this on the youngest revision".  Should we have an
667
 
     SVN_YOUNGEST_REVNUM defined for these purposes? */
668
 
  SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
669
 
                            pool, &root_baton));
 
661
  *updated_repository = FALSE;
 
662
 
 
663
  import_ctx.autoprops = autoprops;
 
664
  SVN_ERR(svn_magic__init(&import_ctx.magic_cookie, ctx->config, pool));
 
665
 
 
666
  /* Get a root dir baton.  We pass the revnum we used for testing our
 
667
     assumptions and obtaining inherited properties. */
 
668
  SVN_ERR(editor->open_root(edit_baton, base_rev, pool, &root_baton));
670
669
 
671
670
  /* Import a file or a directory tree. */
672
671
  SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath, FALSE, FALSE,
697
696
                                        pool, &root_baton));
698
697
 
699
698
          /* Remember that the repository was modified */
700
 
          import_ctx->repos_changed = TRUE;
 
699
          import_ctx.repos_changed = TRUE;
701
700
        }
702
701
    }
703
702
  else if (dirent->kind == svn_node_file)
728
727
 
729
728
      if (!ignores_match)
730
729
        SVN_ERR(import_file(editor, root_baton, local_abspath, edit_path,
731
 
                            dirent, import_ctx, ctx, pool));
 
730
                            dirent, &import_ctx, ctx, pool));
732
731
    }
733
732
  else if (dirent->kind == svn_node_dir)
734
733
    {
748
747
                              root_baton, depth, excludes, global_ignores,
749
748
                              no_ignore, no_autoprops,
750
749
                              ignore_unknown_node_types, filter_callback,
751
 
                              filter_baton, import_ctx, ctx, pool));
 
750
                              filter_baton, &import_ctx, ctx, pool));
752
751
 
753
752
    }
754
753
  else if (dirent->kind == svn_node_none
770
769
        }
771
770
    }
772
771
 
773
 
  if (import_ctx->repos_changed)
774
 
    return editor->close_edit(edit_baton, pool);
775
 
  else
776
 
    return editor->abort_edit(edit_baton, pool);
 
772
  if (import_ctx.repos_changed)
 
773
    {
 
774
      if (ctx->notify_func2)
 
775
        {
 
776
          svn_wc_notify_t *notify;
 
777
          notify = svn_wc_create_notify_url(url,
 
778
                                            svn_wc_notify_commit_finalizing,
 
779
                                            pool);
 
780
          ctx->notify_func2(ctx->notify_baton2, notify, pool);
 
781
        }
 
782
 
 
783
      SVN_ERR(editor->close_edit(edit_baton, pool));
 
784
 
 
785
      *updated_repository = TRUE;
 
786
    }
 
787
 
 
788
  return SVN_NO_ERROR;
777
789
}
778
790
 
779
791
 
809
821
  apr_hash_t *autoprops = NULL;
810
822
  apr_array_header_t *global_ignores;
811
823
  apr_array_header_t *local_ignores_arr;
 
824
  svn_revnum_t base_rev;
 
825
  apr_array_header_t *inherited_props = NULL;
 
826
  apr_hash_t *url_props = NULL;
 
827
  svn_boolean_t updated_repository;
812
828
 
813
829
  if (svn_path_is_url(path))
814
830
    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
816
832
 
817
833
  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
818
834
 
 
835
  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
 
836
 
819
837
  /* Create a new commit item and add it to the array. */
820
838
  if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx))
821
839
    {
828
846
        = apr_array_make(scratch_pool, 1, sizeof(item));
829
847
 
830
848
      item = svn_client_commit_item3_create(scratch_pool);
831
 
      item->path = apr_pstrdup(scratch_pool, path);
 
849
      item->path = local_abspath;
 
850
      item->url = url;
 
851
      item->kind = kind;
832
852
      item->state_flags = SVN_CLIENT_COMMIT_ITEM_ADD;
833
853
      APR_ARRAY_PUSH(commit_items, svn_client_commit_item3_t *) = item;
834
854
 
844
864
        }
845
865
    }
846
866
 
847
 
  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
848
 
 
849
867
  SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
850
868
                                      ctx, scratch_pool, iterpool));
851
869
 
 
870
  SVN_ERR(svn_ra_get_latest_revnum(ra_session, &base_rev, iterpool));
 
871
 
852
872
  /* Figure out all the path components we need to create just to have
853
873
     a place to stick our imported tree. */
854
 
  SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
855
 
                            iterpool));
 
874
  SVN_ERR(svn_ra_check_path(ra_session, "", base_rev, &kind, iterpool));
856
875
 
857
876
  /* We can import into directories, but if a file already exists, that's
858
877
     an error. */
871
890
      APR_ARRAY_PUSH(new_entries, const char *) = dir;
872
891
      SVN_ERR(svn_ra_reparent(ra_session, url, iterpool));
873
892
 
874
 
      SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
875
 
                                iterpool));
 
893
      SVN_ERR(svn_ra_check_path(ra_session, "", base_rev, &kind, iterpool));
876
894
    }
877
895
 
878
896
  /* Reverse the order of the components we added to our NEW_ENTRIES array. */
895
913
  SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
896
914
                                           log_msg, ctx, scratch_pool));
897
915
 
 
916
  /* Obtain properties before opening the commit editor, as at that point we are
 
917
     not allowed to use the existing ra-session */
 
918
  if (! no_ignore /*|| ! no_autoprops*/)
 
919
    {
 
920
      SVN_ERR(svn_ra_get_dir2(ra_session, NULL, NULL, &url_props, "",
 
921
                              base_rev, SVN_DIRENT_KIND, scratch_pool));
 
922
 
 
923
      SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props, "", base_rev,
 
924
                                         scratch_pool, iterpool));
 
925
    }
 
926
 
898
927
  /* Fetch RA commit editor. */
899
928
  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
900
929
                        svn_client__get_shim_callbacks(ctx->wc_ctx,
907
936
  /* Get inherited svn:auto-props, svn:global-ignores, and
908
937
     svn:ignores for the location we are importing to. */
909
938
  if (!no_autoprops)
910
 
    SVN_ERR(svn_client__get_all_auto_props(&autoprops, url, ctx,
911
 
                                           scratch_pool, iterpool));
 
939
    {
 
940
      /* ### This should use inherited_props and url_props to avoid creating
 
941
             another ra session to obtain the same values, but using a possibly
 
942
             different HEAD revision */
 
943
      SVN_ERR(svn_client__get_all_auto_props(&autoprops, url, ctx,
 
944
                                             scratch_pool, iterpool));
 
945
    }
912
946
  if (no_ignore)
913
947
    {
914
948
      global_ignores = NULL;
916
950
    }
917
951
  else
918
952
    {
919
 
      svn_opt_revision_t rev;
920
953
      apr_array_header_t *config_ignores;
921
 
      apr_hash_t *local_ignores_hash;
922
 
 
923
 
      SVN_ERR(svn_client__get_inherited_ignores(&global_ignores, url, ctx,
924
 
                                                scratch_pool, iterpool));
 
954
      svn_string_t *val;
 
955
      int i;
 
956
 
 
957
      global_ignores = apr_array_make(scratch_pool, 64, sizeof(const char *));
 
958
 
925
959
      SVN_ERR(svn_wc_get_default_ignores(&config_ignores, ctx->config,
926
960
                                         scratch_pool));
927
961
      global_ignores = apr_array_append(scratch_pool, global_ignores,
928
962
                                        config_ignores);
929
963
 
930
 
      rev.kind = svn_opt_revision_head;
931
 
      SVN_ERR(svn_client_propget5(&local_ignores_hash, NULL, SVN_PROP_IGNORE, url,
932
 
                                  &rev, &rev, NULL, svn_depth_empty, NULL, ctx,
933
 
                                  scratch_pool, scratch_pool));
 
964
      val = svn_hash_gets(url_props, SVN_PROP_INHERITABLE_IGNORES);
 
965
      if (val)
 
966
        svn_cstring_split_append(global_ignores, val->data, "\n\r\t\v ",
 
967
                                 FALSE, scratch_pool);
 
968
 
 
969
      for (i = 0; i < inherited_props->nelts; i++)
 
970
        {
 
971
          svn_prop_inherited_item_t *elt = APR_ARRAY_IDX(
 
972
            inherited_props, i, svn_prop_inherited_item_t *);
 
973
 
 
974
          val = svn_hash_gets(elt->prop_hash, SVN_PROP_INHERITABLE_IGNORES);
 
975
 
 
976
          if (val)
 
977
            svn_cstring_split_append(global_ignores, val->data, "\n\r\t\v ",
 
978
                                     FALSE, scratch_pool);
 
979
        }
934
980
      local_ignores_arr = apr_array_make(scratch_pool, 1, sizeof(const char *));
935
981
 
936
 
      if (apr_hash_count(local_ignores_hash))
 
982
      val = svn_hash_gets(url_props, SVN_PROP_IGNORE);
 
983
 
 
984
      if (val)
937
985
        {
938
 
          svn_string_t *propval = svn_hash_gets(local_ignores_hash, url);
939
 
          if (propval)
940
 
            {
941
 
              svn_cstring_split_append(local_ignores_arr, propval->data,
942
 
                                       "\n\r\t\v ", FALSE, scratch_pool);
943
 
            }
 
986
          svn_cstring_split_append(local_ignores_arr, val->data,
 
987
                                   "\n\r\t\v ", FALSE, scratch_pool);
944
988
        }
945
989
    }
946
990
 
947
 
  /* If an error occurred during the commit, abort the edit and return
948
 
     the error.  We don't even care if the abort itself fails.  */
949
 
  if ((err = import(local_abspath, new_entries, editor, edit_baton,
950
 
                    depth, excludes, autoprops, local_ignores_arr,
951
 
                    global_ignores, no_ignore, no_autoprops,
952
 
                    ignore_unknown_node_types, filter_callback,
953
 
                    filter_baton, ctx, iterpool)))
 
991
  /* If an error occurred during the commit, properly abort the edit.  */
 
992
  err = svn_error_trace(import(&updated_repository,
 
993
                               local_abspath, url, new_entries, editor,
 
994
                               edit_baton, depth, base_rev, excludes,
 
995
                               autoprops, local_ignores_arr, global_ignores,
 
996
                               no_ignore, no_autoprops,
 
997
                               ignore_unknown_node_types, filter_callback,
 
998
                               filter_baton, ctx, iterpool));
 
999
 
 
1000
  svn_pool_destroy(iterpool);
 
1001
 
 
1002
  if (err || !updated_repository)
954
1003
    {
955
1004
      return svn_error_compose_create(
956
1005
                    err,
957
 
                    editor->abort_edit(edit_baton, iterpool));
 
1006
                    editor->abort_edit(edit_baton, scratch_pool));
958
1007
    }
959
1008
 
960
 
  svn_pool_destroy(iterpool);
961
 
 
962
1009
  return SVN_NO_ERROR;
963
1010
}
964
1011