[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [libqgit2] /: Support cloning a repository
From:       Peter_Kümmel <syntheticpp () gmx ! net>
Date:       2014-02-28 19:59:49
Message-ID: E1WJTb3-0006j7-V2 () scm ! kde ! org
[Download RAW message or body]

Git commit 7ea0526b4ff748463eed158cf96647e6a0d270eb by Peter Kümmel.
Committed on 28/02/2014 at 19:50.
Pushed by kuemmel into branch 'master'.

Support cloning a repository

M  +1    -1    CMakeLists.txt
M  +35   -0    src/qgitrepository.cpp
M  +21   -1    src/qgitrepository.h
M  +2    -0    tests/CMakeLists.txt
A  +107  -0    tests/Clone.cpp     [License: UNKNOWN]  *
M  +22   -1    tests/TestHelpers.h

The files marked with a * at the end have a non valid license. Please read: \
http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are \
listed at that page.


http://commits.kde.org/libqgit2/7ea0526b4ff748463eed158cf96647e6a0d270eb

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f65fee9..b662eb2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -145,7 +145,7 @@ FILE(GLOB QGIT2_HEADERS src/*.h)
 # MOC
 if(Qt5Core_FOUND)
 else()
-    QT4_WRAP_CPP(MOC_SRC src/qgitindexmodel.h)
+    QT4_WRAP_CPP(MOC_SRC src/qgitindexmodel.h src/qgitrepository.h)
 endif()
 
 message(STATUS)
diff --git a/src/qgitrepository.cpp b/src/qgitrepository.cpp
index 77a508c..7d7c0d5 100644
--- a/src/qgitrepository.cpp
+++ b/src/qgitrepository.cpp
@@ -333,4 +333,39 @@ const git_repository* Repository::constData() const
     return d.data();
 }
 
+
+int Repository::fetchProgressCallback(const git_transfer_progress* stats, void* \
data) +{
+    if (!data) {
+        return 1;
+    }
+    Repository* repo = static_cast<Repository*>(data);
+    int percent = (int)(0.5 + 100.0 * ((double)stats->received_objects) / \
((double)stats->total_objects)); +    if (percent != repo->m_clone_progress) {
+        emit repo->cloneProgress(percent);
+        repo->m_clone_progress = percent;
+    }
+    return 0;
+}
+
+
+void Repository::clone(const QString& url, const QString& path)
+{
+    git_clone_options opts;
+    memset(&opts, 0, sizeof(git_clone_options));
+    opts = GIT_CLONE_OPTIONS_INIT;
+
+    opts.remote_callbacks.transfer_progress = &fetchProgressCallback;
+    opts.remote_callbacks.payload = (void*)this;;
+
+    opts.checkout_opts = GIT_CHECKOUT_OPTS_INIT;
+    opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+    m_clone_progress = 0;
+    git_repository* repo = NULL;
+    qGitThrow(git_clone(&repo, qPrintable(url), qPrintable(path), &opts));
+    d = ptr_type(repo, git_repository_free);
+}
+
+
 } // namespace LibQGit2
diff --git a/src/qgitrepository.h b/src/qgitrepository.h
index f09c359..1e07675 100644
--- a/src/qgitrepository.h
+++ b/src/qgitrepository.h
@@ -23,6 +23,7 @@
 
 #include <QtCore/QSharedPointer>
 #include <QtCore/QStringList>
+#include <QtCore/QObject>
 
 #include "libqgit2_export.h"
 
@@ -49,8 +50,10 @@ namespace LibQGit2
      * @ingroup LibQGit2
      * @{
      */
-    class LIBQGIT2_EXPORT Repository
+    class LIBQGIT2_EXPORT Repository : public QObject
     {
+            Q_OBJECT
+
         public:
 
             /**
@@ -413,12 +416,29 @@ namespace LibQGit2
              */
             StatusList status(const StatusOptions *options) const;
 
+            /**
+            * Clone a git repository.
+            *
+            * Signal cloneProgress(int) is emitted with progress in percent.
+            *
+            * @param url URL of the git repository
+            * @param path non-existing directory for the new clone
+            * @throws LibQGit2::Exception
+            */
+            void clone(const QString& url, const QString& path);
+
             git_repository* data() const;
             const git_repository* constData() const;
 
+        signals:
+            void cloneProgress(int);
+
         private:
             typedef QSharedPointer<git_repository> ptr_type;
             ptr_type d;
+
+            int m_clone_progress;
+            static int fetchProgressCallback(const git_transfer_progress* stats, \
void* data);  };
 
     /**@}*/
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b82f42a..a099b01 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -6,6 +6,7 @@ endif()
 set(testdir ${CMAKE_BINARY_DIR}/TestDir)
 file(MAKE_DIRECTORY ${testdir})
 add_definitions(-DTEST_DIR=${testdir})
+remove_definitions(-DMAKE_LIBQGIT2_LIB)
 
 set(existing_repository ${testdir}/existing_repository)
 add_definitions(-DTEST_EXISTING_REPOSITORY=${existing_repository})
@@ -44,3 +45,4 @@ endmacro()
 addTest(Init)
 addTest(Revision)
 addTest(StatusOptions)
+addTest(Clone)
diff --git a/tests/Clone.cpp b/tests/Clone.cpp
new file mode 100644
index 0000000..2aa4eff
--- /dev/null
+++ b/tests/Clone.cpp
@@ -0,0 +1,107 @@
+#include "TestHelpers.h"
+
+#include <QCoreApplication>
+#include <QTimer>
+
+
+#include <iostream>
+#include <bitset>
+
+#include "qgitcommit.h"
+#include "qgitrepository.h"
+
+using namespace LibQGit2;
+
+
+class TestClone : public QObject
+{
+    Q_OBJECT
+
+public:
+    TestClone();
+
+public slots:
+    void cloneProgress(int p) 
+    { 
+        m_clone_progress = p;
+        if (p % 20 == 0) {
+            qDebug() << qPrintable(QString("Progress : %1%").arg(p));
+        }
+    }
+
+private slots:
+    void fileProtocol();
+    void gitProtocol();
+    void httpProtocol();
+    void httpsProtocol();
+
+private:
+    int m_clone_progress;
+    const QString testdir;
+
+    void clone(const QString& url);
+};
+
+
+
+TestClone::TestClone() : testdir(VALUE_TO_STR(TEST_DIR))
+{
+}
+
+
+void TestClone::clone(const QString& url)
+{
+    LibQGit2::Repository repo;
+    connect(&repo, SIGNAL(cloneProgress(int)), this, SLOT(cloneProgress(int)));
+
+    QString dirname = url;
+    dirname.replace(":", "");
+    dirname.replace("//", "/");
+    dirname.replace("//", "/");
+    dirname.replace("/", "_");
+    dirname.replace(".", "_");
+    const QString repoPath = testdir + "/clone_test/" + dirname;
+
+    removeDir(repoPath);
+    sleep::ms(500);
+    m_clone_progress = 0;
+
+    qDebug() << "Cloning " << url;
+    try {
+        repo.clone(url, repoPath);
+    }
+    catch (const LibQGit2::Exception& ex) {
+        QFAIL(ex.what());
+    }
+
+    QCOMPARE(m_clone_progress, 100);
+}
+
+
+void TestClone::fileProtocol()
+{
+    clone("file:///" + VALUE_TO_QSTR(TEST_EXISTING_REPOSITORY) + "/.git");
+}
+
+
+void TestClone::gitProtocol()
+{
+    clone("git://anongit.kde.org/libqgit2");
+}
+
+
+void TestClone::httpProtocol()
+{
+    clone("http://anongit.kde.org/libqgit2");
+}
+
+
+void TestClone::httpsProtocol()
+{
+    clone("https://github.com/lgiordani/libqgit2.git");
+}
+
+
+QTEST_MAIN(TestClone);
+
+#include "Clone.moc"
diff --git a/tests/TestHelpers.h b/tests/TestHelpers.h
index f3e3a9c..fb28672 100644
--- a/tests/TestHelpers.h
+++ b/tests/TestHelpers.h
@@ -3,11 +3,22 @@
 #include <QTest>
 
 #include <QDir>
+#include <QDebug>
+#include <QTimer>
+#include <QThread>
 
 #include "qgitexception.h"
 
 #define TO_STR(s) #s
 #define VALUE_TO_STR(s) TO_STR(s)
+#define VALUE_TO_QSTR(s) QLatin1String(TO_STR(s))
+
+
+struct sleep : QThread
+{
+    static void ms(int msec) { QThread::msleep(msec); }
+};
+
 
 bool removeDir(const QString & dirName)
 {
@@ -21,6 +32,13 @@ bool removeDir(const QString & dirName)
             }
             else {
                 result = QFile::remove(info.absoluteFilePath());
+                if (!result) {
+                    \
QFile(info.absoluteFilePath()).setPermissions(QFile::WriteOwner); +                   \
result = QFile::remove(info.absoluteFilePath()); +                }
+                if (!result) {
+                    qDebug() << "Could not remove " << info.absoluteFilePath();
+                }
             }
 
             if (!result) {
@@ -28,6 +46,9 @@ bool removeDir(const QString & dirName)
             }
         }
         result = dir.rmdir(dirName);
+        if (!result) {
+            qDebug() << "Could not remove " << dirName;
+        }
     }
     return result;
-}
+}
\ No newline at end of file


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic