svn_error_t * svn_repos__adjust_mergeinfo_property(svn_string_t **new_value_p, const svn_string_t *old_value, const char *parent_dir, apr_hash_t *rev_map, svn_revnum_t oldest_dumpstream_rev, apr_int32_t older_revs_offset, svn_repos_notify_func_t notify_func, void *notify_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_string_t prop_val = *old_value; /* Tolerate mergeinfo with "\r\n" line endings because some dumpstream sources might contain as much. If so normalize the line endings to '\n' and notify that we have made this correction. */ if (strstr(prop_val.data, "\r")) { const char *prop_eol_normalized; SVN_ERR(svn_subst_translate_cstring2(prop_val.data, &prop_eol_normalized, "\n", /* translate to LF */ FALSE, /* no repair */ NULL, /* no keywords */ FALSE, /* no expansion */ result_pool)); prop_val.data = prop_eol_normalized; prop_val.len = strlen(prop_eol_normalized); if (notify_func) { svn_repos_notify_t *notify = svn_repos_notify_create( svn_repos_notify_load_normalized_mergeinfo, scratch_pool); notify_func(notify_baton, notify, scratch_pool); } } /* Renumber mergeinfo as appropriate. */ SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val, rev_map, oldest_dumpstream_rev, older_revs_offset, result_pool)); if (parent_dir) { /* Prefix the merge source paths with PARENT_DIR. */ /* ASSUMPTION: All source paths are included in the dump stream. */ SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p, parent_dir, result_pool)); } return SVN_NO_ERROR; }
static irqreturn_t jet_tf_cd_thread(int irq, void *dev_id) { void (*notify_func)(struct platform_device *, int state) = dev_id; int status = gpio_get_value(GPIO_TF_DETECT); notify_func(&s3c_device_hsmmc0, !status); return IRQ_HANDLED; }
static int ext_cd_init(void (*notify_func) (struct platform_device *, int state), void *data) { struct platform_device *pdev = data; struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; struct sdhci_host *host = platform_get_drvdata(pdev); int err, cd_irq, ext_cd_gpio; int status; /* Catch wake lock when card is inserted or removed */ wake_lock_init(&cd_wake_lock, WAKE_LOCK_SUSPEND, "sd_card_detect"); #ifdef CONFIG_REGULATOR host->vmmc = regulator_get(&pdev->dev, "v_mmc"); if (IS_ERR(host->vmmc)) host->vmmc = NULL; else mmc_regulator_get_ocrmask(host->vmmc); #else printk(KERN_ERR "Cannot find the power supply for SD\n"); #endif cd_irq = gpio_to_irq(pdata->ext_cd_gpio); ext_cd_gpio = pdata->ext_cd_gpio; /* * setup GPIO for saarc MMC controller */ err = gpio_request(ext_cd_gpio, "mmc card detect"); if (err) { printk(KERN_ERR "gpio_request err =%d\n", err); goto err_request_cd; } gpio_direction_input(ext_cd_gpio); err = request_threaded_irq(cd_irq, NULL, sdhci_pxa_cd_irq_thread, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC card detect", pdev); if (err) { printk(KERN_ERR "%s: MMC/SD/SDIO: " "can't request card detect IRQ\n", __func__); goto err_request_irq; } status = ext_cd_val(pdata->ext_cd_gpio,pdata->ext_cd_gpio_invert); notify_func(pdev, status); return 0; err_request_irq: gpio_free(ext_cd_gpio); err_request_cd: return -1; }
void mmc_force_presence_change(struct platform_device *pdev) { void (*notify_func)(struct platform_device *, int state) = NULL; mutex_lock(¬ify_lock); #ifdef CONFIG_S3C_DEV_HSMMC3 if (pdev == &s3c_device_hsmmc3) notify_func = hsmmc3_notify_func; #endif if (notify_func) notify_func(pdev, 1); else pr_warn("%s: called for device with no notifier\n", __func__); mutex_unlock(¬ify_lock); }
void mmc_force_presence_change(struct platform_device *pdev, int val) { void (*notify_func)(struct platform_device *, int state) = NULL; mutex_lock(&wlan_mutex_lock); if (pdev == &exynos5_device_dwmci1) { pr_err("%s: called for device exynos5_device_dwmci1\n", __func__); notify_func = wlan_notify_func; } else pr_err("%s: called for device with no notifier, t\n", __func__); if (notify_func) notify_func(pdev, val); else pr_err("%s: called for device with no notifier\n", __func__); mutex_unlock(&wlan_mutex_lock); }
/* Shortcut for the revision and revprop copying for old (1 or 2) format * filesystems without sharding and packing. Copy the non-sharded revision * and revprop files from SRC_FS to DST_FS. Do not re-copy data which * already exists in DST_FS. Do not somehow checkpoint the results in * the 'current' file in DST_FS. Indicate progress via the optional * NOTIFY_FUNC callback using NOTIFY_BATON. Use POOL for temporary * allocations. Also see hotcopy_revisions(). */ static svn_error_t * hotcopy_revisions_old(svn_fs_t *src_fs, svn_fs_t *dst_fs, svn_revnum_t src_youngest, const char *src_revs_dir, const char *dst_revs_dir, const char *src_revprops_dir, const char *dst_revprops_dir, svn_fs_hotcopy_notify_t notify_func, void* notify_baton, svn_cancel_func_t cancel_func, void* cancel_baton, apr_pool_t *pool) { apr_pool_t *iterpool = svn_pool_create(pool); svn_revnum_t rev; for (rev = 0; rev <= src_youngest; rev++) { svn_boolean_t skipped = TRUE; svn_pool_clear(iterpool); if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(hotcopy_io_dir_file_copy(&skipped, src_revs_dir, dst_revs_dir, apr_psprintf(iterpool, "%ld", rev), iterpool)); SVN_ERR(hotcopy_io_dir_file_copy(&skipped, src_revprops_dir, dst_revprops_dir, apr_psprintf(iterpool, "%ld", rev), iterpool)); if (notify_func && !skipped) notify_func(notify_baton, rev, rev, iterpool); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }
static int jet_tf_cd_init(void (*notify_func)(struct platform_device *, int state)) { int ret, status; ret = gpio_request(GPIO_TF_DETECT, "TF detect"); if (ret) return ret; ret = gpio_direction_input(GPIO_TF_DETECT); if (ret) return ret; ret = request_threaded_irq(gpio_to_irq(GPIO_TF_DETECT), NULL, jet_tf_cd_thread, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "TF card detect", notify_func); if (ret) return ret; status = gpio_get_value(GPIO_TF_DETECT); notify_func(&s3c_device_hsmmc0, !status); return 0; }
/* Remove the directory at LOCAL_ABSPATH from revision control, and do the * same to any revision controlled directories underneath LOCAL_ABSPATH * (including directories not referred to by parent svn administrative areas); * then if LOCAL_ABSPATH is empty afterwards, remove it, else rename it to a * unique name in the same parent directory. * * Pass CANCEL_FUNC, CANCEL_BATON to svn_wc_remove_from_revision_control. * * Use SCRATCH_POOL for all temporary allocation. */ static svn_error_t * relegate_dir_external(svn_wc_context_t *wc_ctx, const char *wri_abspath, const char *local_abspath, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { svn_error_t *err = SVN_NO_ERROR; SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath, FALSE, scratch_pool, scratch_pool)); err = svn_wc__external_remove(wc_ctx, wri_abspath, local_abspath, FALSE, cancel_func, cancel_baton, scratch_pool); if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)) { const char *parent_dir; const char *dirname; const char *new_path; svn_error_clear(err); err = SVN_NO_ERROR; svn_dirent_split(&parent_dir, &dirname, local_abspath, scratch_pool); /* Reserve the new dir name. */ SVN_ERR(svn_io_open_uniquely_named(NULL, &new_path, parent_dir, dirname, ".OLD", svn_io_file_del_none, scratch_pool, scratch_pool)); /* Sigh... We must fall ever so slightly from grace. Ideally, there would be no window, however brief, when we don't have a reservation on the new name. Unfortunately, at least in the Unix (Linux?) version of apr_file_rename(), you can't rename a directory over a file, because it's just calling stdio rename(), which says: ENOTDIR A component used as a directory in oldpath or newpath path is not, in fact, a directory. Or, oldpath is a directory, and newpath exists but is not a directory So instead, we get the name, then remove the file (ugh), then rename the directory, hoping that nobody has gotten that name in the meantime -- which would never happen in real life, so no big deal. */ /* Do our best, but no biggy if it fails. The rename will fail. */ svn_error_clear(svn_io_remove_file2(new_path, TRUE, scratch_pool)); /* Rename. If this is still a working copy we should use the working copy rename function (to release open handles) */ err = svn_wc__rename_wc(wc_ctx, local_abspath, new_path, scratch_pool); if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS) { svn_error_clear(err); /* And if it is no longer a working copy, we should just rename it */ err = svn_io_file_rename(local_abspath, new_path, scratch_pool); } /* ### TODO: We should notify the user about the rename */ if (notify_func) { svn_wc_notify_t *notify; notify = svn_wc_create_notify(err ? local_abspath : new_path, svn_wc_notify_left_local_modifications, scratch_pool); notify->kind = svn_node_dir; notify->err = err; notify_func(notify_baton, notify, scratch_pool); } } return svn_error_trace(err); }
/* The main dumper. */ svn_error_t * svn_repos_dump_fs3(svn_repos_t *repos, svn_stream_t *stream, svn_revnum_t start_rev, svn_revnum_t end_rev, svn_boolean_t incremental, svn_boolean_t use_deltas, svn_repos_notify_func_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { const svn_delta_editor_t *dump_editor; void *dump_edit_baton = NULL; svn_revnum_t i; svn_fs_t *fs = svn_repos_fs(repos); apr_pool_t *subpool = svn_pool_create(pool); svn_revnum_t youngest; const char *uuid; int version; svn_boolean_t found_old_reference = FALSE; svn_boolean_t found_old_mergeinfo = FALSE; svn_repos_notify_t *notify; /* Determine the current youngest revision of the filesystem. */ SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); /* Use default vals if necessary. */ if (! SVN_IS_VALID_REVNUM(start_rev)) start_rev = 0; if (! SVN_IS_VALID_REVNUM(end_rev)) end_rev = youngest; if (! stream) stream = svn_stream_empty(pool); /* Validate the revisions. */ if (start_rev > end_rev) return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, _("Start revision %ld" " is greater than end revision %ld"), start_rev, end_rev); if (end_rev > youngest) return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, _("End revision %ld is invalid " "(youngest revision is %ld)"), end_rev, youngest); if ((start_rev == 0) && incremental) incremental = FALSE; /* revision 0 looks the same regardless of whether or not this is an incremental dump, so just simplify things. */ /* Write out the UUID. */ SVN_ERR(svn_fs_get_uuid(fs, &uuid, pool)); /* If we're not using deltas, use the previous version, for compatibility with svn 1.0.x. */ version = SVN_REPOS_DUMPFILE_FORMAT_VERSION; if (!use_deltas) version--; /* Write out "general" metadata for the dumpfile. In this case, a magic header followed by a dumpfile format version. */ SVN_ERR(svn_stream_printf(stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", version)); SVN_ERR(svn_stream_printf(stream, pool, SVN_REPOS_DUMPFILE_UUID ": %s\n\n", uuid)); /* Create a notify object that we can reuse in the loop. */ if (notify_func) notify = svn_repos_notify_create(svn_repos_notify_dump_rev_end, pool); /* Main loop: we're going to dump revision i. */ for (i = start_rev; i <= end_rev; i++) { svn_revnum_t from_rev, to_rev; svn_fs_root_t *to_root; svn_boolean_t use_deltas_for_rev; svn_pool_clear(subpool); /* Check for cancellation. */ if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); /* Special-case the initial revision dump: it needs to contain *all* nodes, because it's the foundation of all future revisions in the dumpfile. */ if ((i == start_rev) && (! incremental)) { /* Special-special-case a dump of revision 0. */ if (i == 0) { /* Just write out the one revision 0 record and move on. The parser might want to use its properties. */ SVN_ERR(write_revision_record(stream, fs, 0, subpool)); to_rev = 0; goto loop_end; } /* Compare START_REV to revision 0, so that everything appears to be added. */ from_rev = 0; to_rev = i; } else { /* In the normal case, we want to compare consecutive revs. */ from_rev = i - 1; to_rev = i; } /* Write the revision record. */ SVN_ERR(write_revision_record(stream, fs, to_rev, subpool)); /* Fetch the editor which dumps nodes to a file. Regardless of what we've been told, don't use deltas for the first rev of a non-incremental dump. */ use_deltas_for_rev = use_deltas && (incremental || i != start_rev); SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton, fs, to_rev, "", stream, notify_func, notify_baton, start_rev, use_deltas_for_rev, FALSE, subpool)); /* Drive the editor in one way or another. */ SVN_ERR(svn_fs_revision_root(&to_root, fs, to_rev, subpool)); /* If this is the first revision of a non-incremental dump, we're in for a full tree dump. Otherwise, we want to simply replay the revision. */ if ((i == start_rev) && (! incremental)) { svn_fs_root_t *from_root; SVN_ERR(svn_fs_revision_root(&from_root, fs, from_rev, subpool)); SVN_ERR(svn_repos_dir_delta2(from_root, "", "", to_root, "", dump_editor, dump_edit_baton, NULL, NULL, FALSE, /* don't send text-deltas */ svn_depth_infinity, FALSE, /* don't send entry props */ FALSE, /* don't ignore ancestry */ subpool)); } else { SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE, dump_editor, dump_edit_baton, NULL, NULL, subpool)); } loop_end: if (notify_func) { notify->revision = to_rev; notify_func(notify_baton, notify, subpool); } if (dump_edit_baton) /* We never get an edit baton for r0. */ { if (((struct edit_baton *)dump_edit_baton)->found_old_reference) found_old_reference = TRUE; if (((struct edit_baton *)dump_edit_baton)->found_old_mergeinfo) found_old_mergeinfo = TRUE; } } if (notify_func) { /* Did we issue any warnings about references to revisions older than the oldest dumped revision? If so, then issue a final generic warning, since the inline warnings already issued might easily be missed. */ notify = svn_repos_notify_create(svn_repos_notify_dump_end, subpool); notify_func(notify_baton, notify, subpool); if (found_old_reference) { notify = svn_repos_notify_create(svn_repos_notify_warning, subpool); notify->warning = svn_repos_notify_warning_found_old_reference; notify->warning_str = _("The range of revisions dumped " "contained references to " "copy sources outside that " "range."); notify_func(notify_baton, notify, subpool); } /* Ditto if we issued any warnings about old revisions referenced in dumped mergeinfo. */ if (found_old_mergeinfo) { notify = svn_repos_notify_create(svn_repos_notify_warning, subpool); notify->warning = svn_repos_notify_warning_found_old_mergeinfo; notify->warning_str = _("The range of revisions dumped " "contained mergeinfo " "which reference revisions outside " "that range."); notify_func(notify_baton, notify, subpool); } } svn_pool_destroy(subpool); return SVN_NO_ERROR; }
svn_error_t * svn_repos_verify_fs2(svn_repos_t *repos, svn_revnum_t start_rev, svn_revnum_t end_rev, svn_repos_notify_func_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { svn_fs_t *fs = svn_repos_fs(repos); svn_revnum_t youngest; svn_revnum_t rev; apr_pool_t *iterpool = svn_pool_create(pool); svn_repos_notify_t *notify; /* Determine the current youngest revision of the filesystem. */ SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); /* Use default vals if necessary. */ if (! SVN_IS_VALID_REVNUM(start_rev)) start_rev = 0; if (! SVN_IS_VALID_REVNUM(end_rev)) end_rev = youngest; /* Validate the revisions. */ if (start_rev > end_rev) return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, _("Start revision %ld" " is greater than end revision %ld"), start_rev, end_rev); if (end_rev > youngest) return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, _("End revision %ld is invalid " "(youngest revision is %ld)"), end_rev, youngest); /* Create a notify object that we can reuse within the loop. */ if (notify_func) notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end, pool); for (rev = start_rev; rev <= end_rev; rev++) { svn_delta_editor_t *dump_editor; void *dump_edit_baton; const svn_delta_editor_t *cancel_editor; void *cancel_edit_baton; svn_fs_root_t *to_root; apr_hash_t *props; svn_pool_clear(iterpool); /* Get cancellable dump editor, but with our close_directory handler. */ SVN_ERR(get_dump_editor((const svn_delta_editor_t **)&dump_editor, &dump_edit_baton, fs, rev, "", svn_stream_empty(pool), notify_func, notify_baton, start_rev, FALSE, TRUE, /* use_deltas, verify */ iterpool)); dump_editor->close_directory = verify_close_directory; SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton, dump_editor, dump_edit_baton, &cancel_editor, &cancel_edit_baton, iterpool)); SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool)); SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE, cancel_editor, cancel_edit_baton, NULL, NULL, iterpool)); SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool)); if (notify_func) { notify->revision = rev; notify_func(notify_baton, notify, iterpool); } } /* We're done. */ if (notify_func) { notify = svn_repos_notify_create(svn_repos_notify_verify_end, iterpool); notify_func(notify_baton, notify, iterpool); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }
/* Copy the revision and revprop files (possibly sharded / packed) from * SRC_FS to DST_FS. Do not re-copy data which already exists in DST_FS. * When copying packed or unpacked shards, checkpoint the result in DST_FS * for every shard by updating the 'current' file if necessary. Assume * the >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT filesystem format without * global next-ID counters. Indicate progress via the optional NOTIFY_FUNC * callback using NOTIFY_BATON. Use POOL for temporary allocations. */ static svn_error_t * hotcopy_revisions(svn_fs_t *src_fs, svn_fs_t *dst_fs, svn_revnum_t src_youngest, svn_revnum_t dst_youngest, svn_boolean_t incremental, const char *src_revs_dir, const char *dst_revs_dir, const char *src_revprops_dir, const char *dst_revprops_dir, svn_fs_hotcopy_notify_t notify_func, void* notify_baton, svn_cancel_func_t cancel_func, void* cancel_baton, apr_pool_t *pool) { fs_fs_data_t *src_ffd = src_fs->fsap_data; fs_fs_data_t *dst_ffd = dst_fs->fsap_data; int max_files_per_dir = src_ffd->max_files_per_dir; svn_revnum_t src_min_unpacked_rev; svn_revnum_t dst_min_unpacked_rev; svn_revnum_t rev; apr_pool_t *iterpool; /* Copy the min unpacked rev, and read its value. */ if (src_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT) { SVN_ERR(svn_fs_fs__read_min_unpacked_rev(&src_min_unpacked_rev, src_fs, pool)); SVN_ERR(svn_fs_fs__read_min_unpacked_rev(&dst_min_unpacked_rev, dst_fs, pool)); /* We only support packs coming from the hotcopy source. * The destination should not be packed independently from * the source. This also catches the case where users accidentally * swap the source and destination arguments. */ if (src_min_unpacked_rev < dst_min_unpacked_rev) return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("The hotcopy destination already contains " "more packed revisions (%lu) than the " "hotcopy source contains (%lu)"), dst_min_unpacked_rev - 1, src_min_unpacked_rev - 1); SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path, PATH_MIN_UNPACKED_REV, pool)); } else { src_min_unpacked_rev = 0; dst_min_unpacked_rev = 0; } if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); /* * Copy the necessary rev files. */ iterpool = svn_pool_create(pool); /* First, copy packed shards. */ for (rev = 0; rev < src_min_unpacked_rev; rev += max_files_per_dir) { svn_boolean_t skipped = TRUE; svn_revnum_t pack_end_rev; svn_pool_clear(iterpool); if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); /* Copy the packed shard. */ SVN_ERR(hotcopy_copy_packed_shard(&skipped, &dst_min_unpacked_rev, src_fs, dst_fs, rev, max_files_per_dir, iterpool)); pack_end_rev = rev + max_files_per_dir - 1; /* Whenever this pack did not previously exist in the destination, * update 'current' to the most recent packed rev (so readers can see * new revisions which arrived in this pack). */ if (pack_end_rev > dst_youngest) { SVN_ERR(svn_fs_fs__write_current(dst_fs, pack_end_rev, 0, 0, iterpool)); } /* When notifying about packed shards, make things simpler by either * reporting a full revision range, i.e [pack start, pack end] or * reporting nothing. There is one case when this approach might not * be exact (incremental hotcopy with a pack replacing last unpacked * revisions), but generally this is good enough. */ if (notify_func && !skipped) notify_func(notify_baton, rev, pack_end_rev, iterpool); /* Remove revision files which are now packed. */ if (incremental) { SVN_ERR(hotcopy_remove_rev_files(dst_fs, rev, rev + max_files_per_dir, max_files_per_dir, iterpool)); if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT) SVN_ERR(hotcopy_remove_revprop_files(dst_fs, rev, rev + max_files_per_dir, max_files_per_dir, iterpool)); } /* Now that all revisions have moved into the pack, the original * rev dir can be removed. */ SVN_ERR(remove_folder(svn_fs_fs__path_rev_shard(dst_fs, rev, iterpool), cancel_func, cancel_baton, iterpool)); if (rev > 0 && dst_ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT) SVN_ERR(remove_folder(svn_fs_fs__path_revprops_shard(dst_fs, rev, iterpool), cancel_func, cancel_baton, iterpool)); } if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); SVN_ERR_ASSERT(rev == src_min_unpacked_rev); SVN_ERR_ASSERT(src_min_unpacked_rev == dst_min_unpacked_rev); /* Now, copy pairs of non-packed revisions and revprop files. * If necessary, update 'current' after copying all files from a shard. */ for (; rev <= src_youngest; rev++) { svn_boolean_t skipped = TRUE; svn_pool_clear(iterpool); if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); /* Copying non-packed revisions is racy in case the source repository is * being packed concurrently with this hotcopy operation. The race can * happen with FS formats prior to SVN_FS_FS__MIN_PACK_LOCK_FORMAT that * support packed revisions. With the pack lock, however, the race is * impossible, because hotcopy and pack operations block each other. * * We assume that all revisions coming after 'min-unpacked-rev' really * are unpacked and that's not necessarily true with concurrent packing. * Don't try to be smart in this edge case, because handling it properly * might require copying *everything* from the start. Just abort the * hotcopy with an ENOENT (revision file moved to a pack, so it is no * longer where we expect it to be). */ /* Copy the rev file. */ SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revs_dir, dst_revs_dir, rev, max_files_per_dir, iterpool)); /* Copy the revprop file. */ SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revprops_dir, dst_revprops_dir, rev, max_files_per_dir, iterpool)); /* Whenever this revision did not previously exist in the destination, * checkpoint the progress via 'current' (do that once per full shard * in order not to slow things down). */ if (rev > dst_youngest) { if (max_files_per_dir && (rev % max_files_per_dir == 0)) { SVN_ERR(svn_fs_fs__write_current(dst_fs, rev, 0, 0, iterpool)); } } if (notify_func && !skipped) notify_func(notify_baton, rev, rev, iterpool); } svn_pool_destroy(iterpool); /* We assume that all revisions were copied now, i.e. we didn't exit the * above loop early. 'rev' was last incremented during exit of the loop. */ SVN_ERR_ASSERT(rev == src_youngest + 1); return SVN_NO_ERROR; }
svn_error_t * svn_wc_exclude(svn_wc_context_t *wc_ctx, const char *local_abspath, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { svn_boolean_t is_root, is_switched; svn_wc__db_status_t status; svn_wc__db_kind_t kind; svn_revnum_t revision; const char *repos_relpath, *repos_root, *repos_uuid; SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, &is_switched, wc_ctx->db, local_abspath, scratch_pool)); if (is_root) { return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Cannot exclude '%s': " "it is a working copy root"), svn_dirent_local_style(local_abspath, scratch_pool)); } if (is_switched) { return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Cannot exclude '%s': " "it is a switched path"), svn_dirent_local_style(local_abspath, scratch_pool)); } SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision, &repos_relpath, &repos_root, &repos_uuid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, wc_ctx->db, local_abspath, scratch_pool, scratch_pool)); switch (status) { case svn_wc__db_status_server_excluded: case svn_wc__db_status_excluded: case svn_wc__db_status_not_present: return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, _("The node '%s' was not found."), svn_dirent_local_style(local_abspath, scratch_pool)); case svn_wc__db_status_added: /* Would have to check parents if we want to allow this */ return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Cannot exclude '%s': it is to be added " "to the repository. Try commit instead"), svn_dirent_local_style(local_abspath, scratch_pool)); case svn_wc__db_status_deleted: /* Would have to check parents if we want to allow this */ return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Cannot exclude '%s': it is to be deleted " "from the repository. Try commit instead"), svn_dirent_local_style(local_abspath, scratch_pool)); case svn_wc__db_status_normal: case svn_wc__db_status_incomplete: default: break; /* Ok to exclude */ } /* ### This could use some kind of transaction */ /* Remove all working copy data below local_abspath */ IGNORE_LOCAL_MOD(svn_wc__internal_remove_from_revision_control( wc_ctx->db, local_abspath, TRUE, FALSE, cancel_func, cancel_baton, scratch_pool)); SVN_ERR(svn_wc__db_base_add_excluded_node(wc_ctx->db, local_abspath, repos_relpath, repos_root, repos_uuid, revision, kind, svn_wc__db_status_excluded, NULL, NULL, scratch_pool)); if (notify_func) { svn_wc_notify_t *notify; notify = svn_wc_create_notify(local_abspath, svn_wc_notify_exclude, scratch_pool); notify_func(notify_baton, notify, scratch_pool); } return SVN_NO_ERROR; }