aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-01-21 12:39:35 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-01-21 12:39:35 +0000
commitf5413106a3cad0840845cc3c7872d7ba94c89798 (patch)
treecdab4dad1d0d942e4e9fba4f7d497a3e9fe9e1c1
parent1405839232f739083b5c84d6587730804d83a934 (diff)
downloadpaludis-f5413106a3cad0840845cc3c7872d7ba94c89798.tar.gz
paludis-f5413106a3cad0840845cc3c7872d7ba94c89798.tar.xz
New pluggable syncer code. Add a new darcs syncer. From David Leverton. Fixes: ticket:32
-rw-r--r--configure.ac12
-rw-r--r--ebuild/Makefile.am2
-rw-r--r--ebuild/syncers/Makefile.am55
-rw-r--r--ebuild/syncers/docvs.in25
-rw-r--r--ebuild/syncers/dodarcs.in24
-rw-r--r--ebuild/syncers/dogit.in19
-rw-r--r--ebuild/syncers/dorsync.in18
-rw-r--r--ebuild/syncers/dosvn.in10
-rw-r--r--paludis/ebuild.cc1
-rw-r--r--paludis/environment.cc9
-rw-r--r--paludis/environment.hh7
-rw-r--r--paludis/environment/default/default_environment.cc18
-rw-r--r--paludis/environment/default/default_environment.hh4
-rw-r--r--paludis/repositories/nothing/nothing_repository.cc23
-rw-r--r--paludis/repositories/nothing/nothing_repository.sr2
-rw-r--r--paludis/repositories/portage/Makefile.am1
-rw-r--r--paludis/repositories/portage/portage_repository.cc13
-rw-r--r--paludis/repositories/portage/xml_things.cc2
-rw-r--r--paludis/syncer.cc288
-rw-r--r--paludis/syncer.hh69
-rw-r--r--paludis/syncer.sr19
-rw-r--r--src/clients/paludis/Makefile.am2
-rw-r--r--src/clients/paludis/applets.cc31
-rwxr-xr-xsrc/clients/paludis/list_sync_formats_TEST3
-rw-r--r--src/clients/paludis/paludis.cc16
25 files changed, 354 insertions, 319 deletions
diff --git a/configure.ac b/configure.ac
index 34d8d59..9d6b381 100644
--- a/configure.ac
+++ b/configure.ac
@@ -267,19 +267,10 @@ dnl {{{ check for cxxflags
if test x = x"$LET_ME_RICE"
then
AC_MSG_CHECKING([for go faster stripes])
- for x in "as-needed" "visibility" "enforce-eh" "fast-math" "rtti"
+ for x in "enforce-eh" "fast-math" "rtti"
do
if echo "${LDFLAGS} ${CFLAGS} ${CXXFLAGS}" | grep "$x" >/dev/null ; then
AC_MSG_RESULT([$x])
- if test $x = "as-needed" ; then
- echo "You shouldn't have as-needed as a global flag. It makes the linker break" 1>&2
- echo "legitimate code. For more details, read http://ciaranm.org/show_post.pl?post_id=13" 1>&2
- fi
- if test $x = "visibility" ; then
- echo "Don't use visibility except for applications that're designed for" 1>&2
- echo "it. At present, Paludis can't be used with visibility because of what" 1>&2
- echo "appears to be an ld.so bug." 1>&2
- fi
AC_MSG_ERROR([Bad ricer. No bagel.])
fi
done
@@ -834,6 +825,7 @@ AC_OUTPUT(
ebuild/Makefile
ebuild/digests/Makefile
ebuild/fetchers/Makefile
+ ebuild/syncers/Makefile
ebuild/utils/Makefile
ebuild/echo_functions.bash
ebuild/work_around_broken_utilities.bash
diff --git a/ebuild/Makefile.am b/ebuild/Makefile.am
index 49696c2..6c9ffcd 100644
--- a/ebuild/Makefile.am
+++ b/ebuild/Makefile.am
@@ -1,6 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
CLEANFILES = *~
-SUBDIRS = . digests fetchers utils
+SUBDIRS = . digests fetchers syncers utils
AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
diff --git a/ebuild/syncers/Makefile.am b/ebuild/syncers/Makefile.am
new file mode 100644
index 0000000..591c133
--- /dev/null
+++ b/ebuild/syncers/Makefile.am
@@ -0,0 +1,55 @@
+MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = *~ .keep docvs+ext docvs+pserver docvs+ssh dodarcs+http dodarcs+ssh dofile dogit dogit+http dogit+ssh dorsync dosvn dosvn+http dosvn+https dosvn+ssh
+SUBDIRS = .
+
+.keep :
+ touch $@
+
+libexecprogdir = $(libexecdir)/paludis/syncers/
+
+libexecprog_SCRIPTS = \
+ docvs+ext \
+ docvs+pserver \
+ docvs+ssh \
+ dodarcs+http \
+ dodarcs+ssh \
+ dofile \
+ dogit \
+ dogit+http \
+ dogit+ssh \
+ dorsync \
+ dosvn \
+ dosvn+http \
+ dosvn+https \
+ dosvn+ssh
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(srcdir)/paludis/syncers/" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/test/run_test.sh
+
+installusersyncersdir = $(datadir)/paludis/syncers
+installusersyncers_DATA = .keep
+
+TESTS =
+EXTRA_DIST = $(libexecprog_SCRIPTS) docvs.in dodarcs.in dogit.in dorsync.in dosvn.in
+
+check_SCRIPTS =
+check_PROGRAMS = $(TESTS)
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+
+docvs+ext docvs+pserver docvs+ssh : docvs.in
+ cat $? > $@
+dodarcs+http dodarcs+ssh : dodarcs.in
+ cat $? > $@
+dogit dogit+http dogit+ssh : dogit.in
+ cat $? > $@
+dofile dorsync : dorsync.in
+ cat $? > $@
+dosvn dosvn+http dosvn+https dosvn+ssh : dosvn.in
+ cat $? > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/ebuild/syncers/docvs.in b/ebuild/syncers/docvs.in
new file mode 100644
index 0000000..2562e60
--- /dev/null
+++ b/ebuild/syncers/docvs.in
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+LOCAL="$1"
+REMOTE="$2"
+
+if [[ "${REMOTE}" == cvs+pserver* ]]; then
+ PSERVER=true
+ REMOTE=":pserver:${REMOTE:14}"
+elif [[ "${REMOTE}" == cvs+ssh* || "${REMOTE}" == cvs+ext* ]]; then
+ PSERVER=false
+ REMOTE=":ext:${REMOTE:10}"
+fi
+
+MODULE="${REMOTE##*:}"
+if [[ "${MODULE}" == "${REMOTE}" ]]; then
+ source "${PALUDIS_EBUILD_DIR}/echo_functions.bash"
+ eerror "'${REMOTE}' is not a valid URL for a CVS repository"
+ exit 1
+fi
+REMOTE="${REMOTE%:*}"
+
+[[ ! -d "${LOCAL}" ]] && mkdir -p "${LOCAL}"
+cd "${LOCAL}" && ( ! ${PSERVER} || cvs -d "${REMOTE}" login ) &&
+ cvs -d "${REMOTE}" checkout "${MODULE}"
+
diff --git a/ebuild/syncers/dodarcs.in b/ebuild/syncers/dodarcs.in
new file mode 100644
index 0000000..15e0b88
--- /dev/null
+++ b/ebuild/syncers/dodarcs.in
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+LOCAL="$1"
+REMOTE="$2"
+
+if [[ "${REMOTE}" == darcs+ssh* ]]; then
+ REMOTE="${REMOTE:12}"
+elif [[ "${REMOTE}" == darcs+* ]]; then
+ REMOTE="${REMOTE:6}"
+fi
+
+if [[ -d "${LOCAL}" && ! -d "${LOCAL}/_darcs" ]]; then
+ source "${PALUDIS_EBUILD_DIR}/echo_functions.bash"
+ eerror "'${LOCAL}' exists but it is not a Darcs repository"
+ exit 1
+fi
+
+if [[ -d "${LOCAL}/_darcs" ]]; then
+ cd "${LOCAL}" && darcs pull --all --set-scripts-executable "${REMOTE}"
+else
+ darcs get --partial --set-scripts-executable --repo-name="${LOCAL}" \
+ "${REMOTE}"
+fi
+
diff --git a/ebuild/syncers/dogit.in b/ebuild/syncers/dogit.in
new file mode 100644
index 0000000..9ee055d
--- /dev/null
+++ b/ebuild/syncers/dogit.in
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+LOCAL="$1"
+REMOTE="$2"
+
+[[ "${REMOTE}" == git+http* ]] && REMOTE="${REMOTE:4}"
+
+if [[ -d "${LOCAL}" && ! -d "${LOCAL}/.git" ]]; then
+ source "${PALUDIS_EBUILD_DIR}/echo_functions.bash"
+ eerror "'${LOCAL}' exists but it is not a Git repository"
+ exit 1
+fi
+
+if [[ -d "${LOCAL}/.git" ]]; then
+ cd "${LOCAL}" && git pull
+else
+ git clone "${REMOTE}" "${LOCAL}"
+fi
+
diff --git a/ebuild/syncers/dorsync.in b/ebuild/syncers/dorsync.in
new file mode 100644
index 0000000..f0ee64d
--- /dev/null
+++ b/ebuild/syncers/dorsync.in
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+LOCAL="$1"
+REMOTE="$2"
+
+[[ "${REMOTE}" == file* ]] && REMOTE="${REMOTE:7}"
+
+if [[ -n "${PALUDIS_SYNC_EXCLUDE_FROM}" ]]; then
+ EXCLUDE=( --exclude-from "${PALUDIS_SYNC_EXCLUDE_FROM}" )
+else
+ EXCLUDE=( )
+fi
+
+rsync --recursive --links --safe-links --perms --times --compress --force \
+ --whole-file --delete --delete-after --stats --timeout=180 \
+ --exclude=/distfiles --exclude=/packages --exclude=/local \
+ --exclude=/.cache --progress "${EXCLUDE[@]}" "${REMOTE}" "${LOCAL}/"
+
diff --git a/ebuild/syncers/dosvn.in b/ebuild/syncers/dosvn.in
new file mode 100644
index 0000000..a5484ad
--- /dev/null
+++ b/ebuild/syncers/dosvn.in
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+LOCAL="$1"
+REMOTE="$2"
+
+[[ "${REMOTE}" == svn+http* || "${REMOTE}" == svn+https* ]] &&
+ REMOTE="${REMOTE:4}"
+
+svn checkout "${REMOTE}" "${LOCAL}/"
+
diff --git a/paludis/ebuild.cc b/paludis/ebuild.cc
index 5b6a8d1..babf5ef 100644
--- a/paludis/ebuild.cc
+++ b/paludis/ebuild.cc
@@ -107,6 +107,7 @@ EbuildCommand::operator() ()
("PALUDIS_BASHRC_FILES", params.environment->bashrc_files())
("PALUDIS_HOOK_DIRS", params.environment->hook_dirs())
("PALUDIS_FETCHERS_DIRS", params.environment->fetchers_dirs())
+ ("PALUDIS_SYNCERS_DIRS", params.environment->syncers_dirs())
("PALUDIS_COMMAND", params.environment->paludis_command())
("KV", kernel_version())
("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
diff --git a/paludis/environment.cc b/paludis/environment.cc
index 940b79e..1bd9cb4 100644
--- a/paludis/environment.cc
+++ b/paludis/environment.cc
@@ -467,6 +467,15 @@ Environment::fetchers_dirs() const
;
}
+std::string
+Environment::syncers_dirs() const
+{
+ return
+ DATADIR "/paludis/syncers" " "
+ LIBEXECDIR "/paludis/syncers" " "
+ ;
+}
+
namespace
{
static const std::multimap<std::string, std::string> environment_mirrors;
diff --git a/paludis/environment.hh b/paludis/environment.hh
index e39a173..1a53e37 100644
--- a/paludis/environment.hh
+++ b/paludis/environment.hh
@@ -218,6 +218,13 @@ namespace paludis
virtual std::string fetchers_dirs() const;
/**
+ * Our syncers directories.
+ *
+ * Default behaviour: user then paludis syncer dirs.
+ */
+ virtual std::string syncers_dirs() const;
+
+ /**
* How to run paludis.
*/
virtual std::string paludis_command() const = 0;
diff --git a/paludis/environment/default/default_environment.cc b/paludis/environment/default/default_environment.cc
index 85b0738..690c4c2 100644
--- a/paludis/environment/default/default_environment.cc
+++ b/paludis/environment/default/default_environment.cc
@@ -680,6 +680,24 @@ DefaultEnvironment::hook_dirs() const
return join(hook_dirs_ref.begin(), hook_dirs_ref.end(), " ");
}
+std::string
+DefaultEnvironment::fetchers_dirs() const
+{
+ std::string dirs(stringify(FSEntry(DefaultConfig::get_instance()->config_dir()) / "fetchers"));
+ if (getenv_with_default("PALUDIS_NO_GLOBAL_FETCHERS", "").empty())
+ dirs += " " + Environment::fetchers_dirs();
+ return dirs;
+}
+
+std::string
+DefaultEnvironment::syncers_dirs() const
+{
+ std::string dirs(stringify(FSEntry(DefaultConfig::get_instance()->config_dir()) / "syncers"));
+ if (getenv_with_default("PALUDIS_NO_GLOBAL_SYNCERS", "").empty())
+ dirs += " " + Environment::syncers_dirs();
+ return dirs;
+}
+
CompositeDepAtom::Pointer
DefaultEnvironment::local_package_set(const SetName & s) const
{
diff --git a/paludis/environment/default/default_environment.hh b/paludis/environment/default/default_environment.hh
index ab9d9ac..7babf7b 100644
--- a/paludis/environment/default/default_environment.hh
+++ b/paludis/environment/default/default_environment.hh
@@ -69,6 +69,10 @@ namespace paludis
virtual std::string hook_dirs() const;
+ virtual std::string fetchers_dirs() const;
+
+ virtual std::string syncers_dirs() const;
+
virtual std::string paludis_command() const;
virtual UseFlagNameCollection::ConstPointer known_use_expand_names(const UseFlagName &,
diff --git a/paludis/repositories/nothing/nothing_repository.cc b/paludis/repositories/nothing/nothing_repository.cc
index 1c9c29d..5c3b8ec 100644
--- a/paludis/repositories/nothing/nothing_repository.cc
+++ b/paludis/repositories/nothing/nothing_repository.cc
@@ -65,6 +65,9 @@ namespace paludis
/// (Empty) provides map.
const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+ /// Environment (for syncing)
+ const Environment * environment;
+
/// Constructor.
Implementation(const NothingRepositoryParams &);
@@ -76,7 +79,8 @@ namespace paludis
name(p.name),
location(p.location),
sync(p.sync),
- sync_exclude(p.sync_exclude)
+ sync_exclude(p.sync_exclude),
+ environment(p.environment)
{
}
@@ -174,7 +178,7 @@ NothingRepository::do_version_metadata(
CountedPtr<Repository>
NothingRepository::make_nothing_repository(
- Environment * const,
+ Environment * const env,
AssociativeCollection<std::string, std::string>::ConstPointer m)
{
std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
@@ -206,7 +210,8 @@ NothingRepository::make_nothing_repository(
.name(name)
.location(location)
.sync(sync)
- .sync_exclude(sync_exclude)));
+ .sync_exclude(sync_exclude)
+ .environment(env)));
}
NothingRepositoryConfigurationError::NothingRepositoryConfigurationError(
@@ -229,14 +234,12 @@ NothingRepository::do_sync() const
if (_imp->sync.empty())
return false;
- std::string::size_type p(_imp->sync.find("://")), q(_imp->sync.find(":"));
- if (std::string::npos == p)
- throw NoSuchSyncerError(_imp->sync);
-
+ DefaultSyncer syncer(SyncerParams::create()
+ .environment(_imp->environment)
+ .local(stringify(_imp->location))
+ .remote(_imp->sync));
SyncOptions opts(_imp->sync_exclude);
-
- SyncerMaker::get_instance()->find_maker(_imp->sync.substr(0, std::min(p, q)))(
- stringify(_imp->location), _imp->sync.substr(q < p ? q + 1 : 0))->sync(opts);
+ syncer.sync(opts);
return true;
}
diff --git a/paludis/repositories/nothing/nothing_repository.sr b/paludis/repositories/nothing/nothing_repository.sr
index fab9d3e..a9067d7 100644
--- a/paludis/repositories/nothing/nothing_repository.sr
+++ b/paludis/repositories/nothing/nothing_repository.sr
@@ -8,6 +8,8 @@ make_class_NothingRepositoryParams()
key sync std::string
key sync_exclude std::string
+ key environment "const Environment *"
+
allow_named_args
doxygen_comment << "END"
diff --git a/paludis/repositories/portage/Makefile.am b/paludis/repositories/portage/Makefile.am
index da58cd1..71ea5fc 100644
--- a/paludis/repositories/portage/Makefile.am
+++ b/paludis/repositories/portage/Makefile.am
@@ -191,6 +191,7 @@ else
libpaludisportagerepositoryxmlthings_la_LIBADD = @LIBXML2DEPS_LIBS@ \
$(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
$(top_builddir)/paludis/libxml/libpaludislibxml.la
endif
diff --git a/paludis/repositories/portage/portage_repository.cc b/paludis/repositories/portage/portage_repository.cc
index 9fdd884..3c8da57 100644
--- a/paludis/repositories/portage/portage_repository.cc
+++ b/paludis/repositories/portage/portage_repository.cc
@@ -782,15 +782,12 @@ PortageRepository::do_sync() const
if (_imp->params.sync.empty())
return false;
- std::string::size_type p(_imp->params.sync.find("://")), q(_imp->params.sync.find(":"));
- if (std::string::npos == p)
- throw NoSuchSyncerError(_imp->params.sync);
-
+ DefaultSyncer syncer(SyncerParams::create()
+ .environment(_imp->params.environment)
+ .local(stringify(_imp->params.location))
+ .remote(_imp->params.sync));
SyncOptions opts(_imp->params.sync_exclude);
-
- SyncerMaker::get_instance()->find_maker(_imp->params.sync.substr(0, std::min(p, q)))(
- stringify(_imp->params.location),
- _imp->params.sync.substr(q < p ? q + 1 : 0))->sync(opts);
+ syncer.sync(opts);
return true;
}
diff --git a/paludis/repositories/portage/xml_things.cc b/paludis/repositories/portage/xml_things.cc
index 10dc694..4d5fcf2 100644
--- a/paludis/repositories/portage/xml_things.cc
+++ b/paludis/repositories/portage/xml_things.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
diff --git a/paludis/syncer.cc b/paludis/syncer.cc
index 70f613a..2e7bbe6 100644
--- a/paludis/syncer.cc
+++ b/paludis/syncer.cc
@@ -1,8 +1,9 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
* Copyright (c) 2006 Stephen Klimaszewski <steev@gentoo.org>
+ * Copyright (c) 2007 David Leverton <u01drl3@abdn.ac.uk>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -19,8 +20,13 @@
*/
#include "syncer.hh"
+#include <paludis/about.hh>
+#include <paludis/environment.hh>
#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+#include <list>
/** \file
* Implementation for Syncer classes.
@@ -37,254 +43,74 @@ NoSuchSyncerError::NoSuchSyncerError(const std::string & format) throw () :
{
}
-namespace
-{
- /**
- * A Syncer for rsync:// syncing.
- *
- * \ingroup grpsyncer
- */
- class RsyncSyncer :
- public Syncer
- {
- private:
- std::string _local;
- std::string _remote;
-
- protected:
- RsyncSyncer(const std::string & local, const std::string & remote) :
- _local(local),
- _remote(remote)
- {
- if ((0 == _remote.compare(0, 4, "file", 0, 4)))
- _remote.erase(0, 7);
- }
-
- public:
- virtual void sync(const SyncOptions &) const;
-
- static Syncer::Pointer make(const std::string & local, const std::string & remote)
- {
- return Syncer::Pointer(new RsyncSyncer(local, remote));
- }
- };
-
- /**
- * A Syncer for svn:// (subversion) syncing.
- *
- * \ingroup grpsyncer
- */
- class SvnSyncer :
- public Syncer
- {
- private:
- std::string _local;
- std::string _remote;
-
- protected:
- SvnSyncer(const std::string & local, const std::string & remote) :
- _local(local),
- _remote(remote)
- {
- if ((0 == _remote.compare(0, 8, "svn+http", 0, 8)) || (0 == _remote.compare(0, 9, "svn+https", 0, 9)))
- _remote.erase(0, 4);
- }
-
- public:
- virtual void sync(const SyncOptions &) const;
- static Syncer::Pointer make(const std::string & local, const std::string & remote)
- {
- return Syncer::Pointer(new SvnSyncer(local, remote));
- }
- };
-
- /**
- * A Syncer for Git syncing.
- *
- * \ingroup grpsyncer
- */
- class GitSyncer :
- public Syncer
- {
- private:
- std::string _local;
- std::string _remote;
-
- protected:
- GitSyncer(const std::string & local, const std::string & remote) :
- _local(local),
- _remote(remote)
- {
- if (0 == _remote.compare(0, 8, "git+http", 0, 8))
- _remote.erase(0, 4);
- }
-
- public:
- virtual void sync(const SyncOptions &) const;
- static Syncer::Pointer make(const std::string & local, const std::string & remote)
- {
- return Syncer::Pointer(new GitSyncer(local, remote));
- }
- };
-
- /**
- * A Syncer for cvs+ext://, cvs+pserver:// (CVS) syncing.
- *
- * \ingroup grpsyncer
- */
- class CvsSyncer :
- public Syncer
- {
- private:
- std::string _local;
- std::string _remote;
- std::string _module;
-
- bool _pserver;
-
- protected:
- CvsSyncer(const std::string & local, const std::string & remote) :
- _local(local),
- _remote(remote),
- _pserver(false)
- {
- if (0 == _remote.compare(0, 11, "cvs+pserver", 0, 11))
- {
- _remote = ":pserver:" + _remote.erase(0, 14);
- _pserver = true;
- }
- else if ((0 == _remote.compare(0, 7, "cvs+ssh", 0, 7)) || (0 == _remote.compare(0, 7, "cvs+ext", 0, 7)))
- {
- _remote = ":ext:" + _remote.erase(0, 10);
- }
-
- std::string::size_type pos(_remote.find_last_of(":"));
-
- if (std::string::npos == pos)
- throw SyncCvsUrlInvalid(_remote);
-
- _module = std::string(_remote, pos + 1);
- _remote.erase(pos);
- }
-
- public:
- virtual void sync(const SyncOptions &) const;
- static Syncer::Pointer make(const std::string & local, const std::string & remote)
- {
- return Syncer::Pointer(new CvsSyncer(local, remote));
- }
- };
-}
-
-void
-RsyncSyncer::sync(const SyncOptions & opts) const
+SyncFailedError::SyncFailedError(const std::string & local, const std::string & remote) throw () :
+ PackageActionError("sync of '" + local + "' from '" + remote + "' failed")
{
- Context context("When performing sync via rsync from '" + _remote + "' to '"
- + _local + "':");
-
- FSEntry(_local).mkdir();
-
- std::string exclude;
- if (! opts.exclude_from.empty())
- exclude = "--exclude-from " + opts.exclude_from + " ";
-
- std::string cmd("rsync --recursive --links --safe-links --perms --times "
- "--compress --force --whole-file --delete --delete-after --stats "
- "--timeout=180 --exclude=/distfiles --exclude=/packages "
- "--exclude=/local --exclude=/.cache --progress " + exclude + "'" + _remote +
- "' '" + _local + "/'");
-
- if (0 != run_command(cmd))
- throw SyncFailedError(_local, _remote);
}
-void
-SvnSyncer::sync(const SyncOptions &) const
+SyncFailedError::SyncFailedError(const std::string & msg) throw () :
+ PackageActionError(msg)
{
- Context context("When performing sync via subversion from '" + _remote + "' to '"
- + _local + "':");
-
- std::string cmd("svn checkout '" + _remote + "' '" + _local + "/'");
-
- if (0 != run_command(cmd))
- throw SyncFailedError(_local, _remote);
}
-void
-GitSyncer::sync(const SyncOptions &) const
+DefaultSyncer::DefaultSyncer(const SyncerParams & params)
+ : _local(params.local), _remote(params.remote), _environment(params.environment)
{
- Context context("When performing sync via git from '" + _remote + "' to '"
- + _local + "':");
-
- FSEntry git_dir(_local + "/.git");
- FSEntry repo_dir(_local);
- int status;
+ std::string::size_type p(_remote.find("://")), q(_remote.find(":"));
+ if (std::string::npos == p)
+ throw NoSuchSyncerError(_remote);
- if (repo_dir.is_directory() && ! git_dir.is_directory())
- throw SyncGitDirectoryExists(_local);
+ const std::string & format = _remote.substr(0, std::min(p, q));
+ if (q < p)
+ _remote = _remote.substr(q < p ? q + 1 : 0);
- if (git_dir.is_directory())
- status = run_command_in_directory("git pull", repo_dir);
- else
- status = run_command("git clone '"+ _remote + "' '" + _local + "'");
+ std::list<std::string> syncers_dirs;
+ WhitespaceTokeniser::get_instance()->tokenise(_environment->syncers_dirs(),
+ std::back_inserter(syncers_dirs));
- if (0 != status)
- throw SyncFailedError(_local, _remote);
-}
-
-void
-CvsSyncer::sync(const SyncOptions &) const
-{
- Context context("When performing sync via CVS from '" + _remote + "' to '"
- + _local + "':");
-
- std::string cmd("cvs -d '" + _remote + "' login");
- FSEntry d(FSEntry(_local).dirname());
+ Log::get_instance()->message(ll_debug, lc_context, "looking for syncer protocol '"
+ + stringify(format) + "'");
- if (_pserver)
+ FSEntry syncer("/var/empty");
+ bool ok(false);
+ for (std::list<std::string>::const_iterator d(syncers_dirs.begin()),
+ d_end(syncers_dirs.end()) ; d != d_end && ! ok; ++d)
{
- if (0 != run_command_in_directory(cmd, d))
- throw SyncFailedError(_local, _remote + ":" + _module);
- }
+ syncer = FSEntry(*d) / ("do" + format);
+ if (syncer.exists() && syncer.has_permission(fs_ug_owner, fs_perm_execute))
+ ok = true;
- cmd = std::string("cvs -d '" + _remote + "' checkout '" + _module + "'");
- if (0 != run_command_in_directory(cmd, d))
- throw SyncFailedError(_local, _remote + ":" + _module);
-}
+ Log::get_instance()->message(ll_debug, lc_no_context, "Trying '" + stringify(syncer) + "': "
+ + (ok ? "ok" : "not ok"));
+ }
-SyncFailedError::SyncFailedError(const std::string & local, const std::string & remote) throw () :
- PackageActionError("sync of '" + local + "' from '" + remote + "' failed")
-{
-}
+ if (! ok)
+ throw NoSuchSyncerError(format);
-SyncFailedError::SyncFailedError(const std::string & msg) throw () :
- PackageActionError(msg)
-{
+ _syncer = stringify(syncer);
}
-SyncGitDirectoryExists::SyncGitDirectoryExists(const std::string & local) throw () :
- SyncFailedError("'" + local + "' exists but it is not a Git repository")
+void
+DefaultSyncer::sync(const SyncOptions & opts) const
{
-}
-SyncCvsUrlInvalid::SyncCvsUrlInvalid(const std::string & url) throw () :
- SyncFailedError("'" + url + "' is not a valid URL for a CVS repository")
-{
-}
-
-SyncerMaker::SyncerMaker()
-{
- register_maker("rsync", &RsyncSyncer::make);
- register_maker("file", &RsyncSyncer::make);
- register_maker("svn", &SvnSyncer::make);
- register_maker("svn+ssh", &SvnSyncer::make);
- register_maker("svn+http", &SvnSyncer::make);
- register_maker("svn+https", &SvnSyncer::make);
- register_maker("git", &GitSyncer::make);
- register_maker("git+ssh", &GitSyncer::make);
- register_maker("git+http", &GitSyncer::make);
- register_maker("cvs+ext", &CvsSyncer::make);
- register_maker("cvs+ssh", &CvsSyncer::make);
- register_maker("cvs+pserver", &CvsSyncer::make);
+ MakeEnvCommand cmd(make_env_command(stringify(_syncer) + " '" + _local + "' '" + _remote + "'")
+ ("PKGMANAGER", PALUDIS_PACKAGE "-" + stringify(PALUDIS_VERSION_MAJOR) + "." +
+ stringify(PALUDIS_VERSION_MINOR) + "." +
+ stringify(PALUDIS_VERSION_MICRO) +
+ (std::string(PALUDIS_SUBVERSION_REVISION).empty() ?
+ std::string("") : "-r" + std::string(PALUDIS_SUBVERSION_REVISION)))
+ ("PALUDIS_CONFIG_DIR", SYSCONFDIR "/paludis/")
+ ("PALUDIS_BASHRC_FILES", _environment->bashrc_files())
+ ("PALUDIS_HOOK_DIRS", _environment->hook_dirs())
+ ("PALUDIS_FETCHERS_DIRS", _environment->fetchers_dirs())
+ ("PALUDIS_SYNCERS_DIRS", _environment->syncers_dirs())
+ ("PALUDIS_COMMAND", _environment->paludis_command())
+ ("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ ("PALUDIS_EBUILD_DIR", getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis"))
+ ("PALUDIS_SYNC_EXCLUDE_FROM", opts.exclude_from));
+
+ if (run_command(cmd))
+ throw SyncFailedError(_local, _remote);
}
diff --git a/paludis/syncer.hh b/paludis/syncer.hh
index c439348..167eeea 100644
--- a/paludis/syncer.hh
+++ b/paludis/syncer.hh
@@ -20,7 +20,6 @@
#ifndef PALUDIS_GUARD_PALUDIS_SYNCER_HH
#define PALUDIS_GUARD_PALUDIS_SYNCER_HH 1
-#include <paludis/util/virtual_constructor.hh>
#include <paludis/util/exception.hh>
#include <paludis/repository.hh>
#include <string>
@@ -68,57 +67,58 @@ namespace paludis
};
/**
- * Thrown if a sync fails.
+ * A Syncer subclass that uses a program from the syncers/ directory.
*
* \ingroup grpsyncer
- * \ingroup grpexceptions
*/
- class SyncFailedError :
- public PackageActionError
+ class DefaultSyncer :
+ public Syncer
{
- protected:
+ private:
+ std::string _local, _remote;
+ const Environment *_environment;
+
+ std::string _syncer;
+
+ public:
/**
* Constructor.
*/
- SyncFailedError(const std::string & msg) throw ();
+ DefaultSyncer(const SyncerParams &);
- public:
/**
- * Constructor.
+ * Destructor.
*/
- SyncFailedError(const std::string & local, const std::string & remote) throw ();
+ virtual ~DefaultSyncer()
+ {
+ }
+
+ /**
+ * Perform the sync.
+ */
+ virtual void sync(const SyncOptions &) const;
};
/**
- * Thrown if a directory exists where a Git repository should be cloned.
+ * Thrown if a sync fails.
*
* \ingroup grpsyncer
* \ingroup grpexceptions
*/
- class SyncGitDirectoryExists :
- public SyncFailedError
+ class SyncFailedError :
+ public PackageActionError
{
- public:
+ protected:
/**
* Constructor.
*/
- SyncGitDirectoryExists(const std::string & local) throw ();
- };
+ SyncFailedError(const std::string & msg) throw ();
- /**
- * Thrown if a given CVS sync URL is invalid.
- *
- * \ingroup grpsyncer
- * \ingroup grpexceptions
- */
- class SyncCvsUrlInvalid :
- public SyncFailedError
- {
public:
/**
* Constructor.
*/
- SyncCvsUrlInvalid(const std::string & url) throw ();
+ SyncFailedError(const std::string & local, const std::string & remote) throw ();
};
/**
@@ -135,23 +135,6 @@ namespace paludis
*/
NoSuchSyncerError(const std::string & format) throw ();
};
-
-
- /**
- * Virtual constructor for Syncer subclasses.
- *
- * \ingroup grpsyncer
- */
- class SyncerMaker :
- public VirtualConstructor<std::string, Syncer::Pointer (*) (const std::string &, const std::string &),
- virtual_constructor_not_found::ThrowException<NoSuchSyncerError> >,
- public InstantiationPolicy<SyncerMaker, instantiation_method::SingletonAsNeededTag>
- {
- friend class InstantiationPolicy<SyncerMaker, instantiation_method::SingletonAsNeededTag>;
-
- private:
- SyncerMaker();
- };
}
#endif
diff --git a/paludis/syncer.sr b/paludis/syncer.sr
index dc5f030..d2c45a4 100644
--- a/paludis/syncer.sr
+++ b/paludis/syncer.sr
@@ -16,3 +16,22 @@ make_class_SyncOptions()
END
}
+make_class_SyncerParams()
+{
+ key local std::string
+ key remote std::string
+
+ key environment "const Environment *"
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for a Syncer.
+ *
+ * \see Syncer
+ * \ingroup grpsyncer
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
diff --git a/src/clients/paludis/Makefile.am b/src/clients/paludis/Makefile.am
index 37b84f3..7aa62da 100644
--- a/src/clients/paludis/Makefile.am
+++ b/src/clients/paludis/Makefile.am
@@ -81,7 +81,7 @@ TESTS_ENVIRONMENT = env \
SYSCONFDIR="$(sysconfdir)" \
bash $(top_srcdir)/test/run_test.sh bash
-TESTS = version_TEST help_TEST list_sync_formats_TEST \
+TESTS = version_TEST help_TEST \
list_repository_formats_TEST list_dep_tag_categories_TEST \
exception_TEST install_TEST upgrade_TEST args_from_environment_TEST
diff --git a/src/clients/paludis/applets.cc b/src/clients/paludis/applets.cc
index 163c0e7..17b578b 100644
--- a/src/clients/paludis/applets.cc
+++ b/src/clients/paludis/applets.cc
@@ -25,6 +25,8 @@
#include <paludis/paludis.hh>
#include <paludis/util/log.hh>
#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/tokeniser.hh>
#include <paludis/environment/default/default_environment.hh>
#include <paludis/repositories/repository_maker.hh>
#include <string>
@@ -185,10 +187,33 @@ int do_list_repository_formats()
int do_list_sync_protocols()
{
- int return_code(1);
-
std::set<std::string> keys;
- SyncerMaker::get_instance()->copy_keys(std::inserter(keys, keys.begin()));
+
+ Environment * const env(DefaultEnvironment::get_instance());
+ std::list<std::string> syncers_dirs;
+ WhitespaceTokeniser::get_instance()->tokenise(env->syncers_dirs(),
+ std::back_inserter(syncers_dirs));
+
+ for (std::list<std::string>::const_iterator d(syncers_dirs.begin()),
+ d_end(syncers_dirs.end()) ; d != d_end ; ++d)
+ {
+ FSEntry dir(*d);
+ if (! dir.is_directory())
+ continue;
+
+ for (DirIterator f(dir), f_end; f != f_end; ++f)
+ {
+ std::string name(f->basename());
+ if (f->has_permission(fs_ug_owner, fs_perm_execute) &&
+ 0 == name.compare(0, 2, "do", 0, 2))
+ {
+ name.erase(0, 2);
+ keys.insert(name);
+ }
+ }
+ }
+
+ int return_code(1);
if (! keys.empty())
{
diff --git a/src/clients/paludis/list_sync_formats_TEST b/src/clients/paludis/list_sync_formats_TEST
deleted file mode 100755
index f638b22..0000000
--- a/src/clients/paludis/list_sync_formats_TEST
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-PALUDIS_SKIP_CONFIG=yes ./paludis --list-sync-protocols
diff --git a/src/clients/paludis/paludis.cc b/src/clients/paludis/paludis.cc
index ea96575..bf32fe2 100644
--- a/src/clients/paludis/paludis.cc
+++ b/src/clients/paludis/paludis.cc
@@ -253,14 +253,6 @@ main(int argc, char *argv[])
/* these actions don't need DefaultConfig or paludis_command. */
- if (CommandLine::get_instance()->a_list_sync_protocols.specified())
- {
- if (! CommandLine::get_instance()->empty())
- throw args::DoHelp("list-sync-protocols action takes no parameters");
-
- return do_list_sync_protocols();
- }
-
if (CommandLine::get_instance()->a_list_repository_formats.specified())
{
if (! CommandLine::get_instance()->empty())
@@ -331,6 +323,14 @@ main(int argc, char *argv[])
throw args::DoHelp("resume-command-template must contain at least XXXXXX");
}
+ if (CommandLine::get_instance()->a_list_sync_protocols.specified())
+ {
+ if (! CommandLine::get_instance()->empty())
+ throw args::DoHelp("list-sync-protocols action takes no parameters");
+
+ return do_list_sync_protocols();
+ }
+
if (CommandLine::get_instance()->a_info.specified())
{
display_version();