1
0
mirror of https://github.com/QRouland/UTPass.git synced 2025-06-24 22:42:28 +00:00

Add support for ssh clone

This commit is contained in:
2025-02-21 15:50:27 +01:00
parent 5683db69c7
commit 884488b9ed
16 changed files with 558 additions and 184 deletions

View File

@ -12,8 +12,15 @@ extern "C" {
#include "jobs/gitjob.h"
Git::Git():
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1)))
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1))),
m_ssh_homedir (QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/.ssh"))
{
qDebug() << "[Git] SSH Home is " << m_ssh_homedir.absolutePath();
QDir m_ssh_homedir(this->m_ssh_homedir);
if (!m_ssh_homedir.exists()) {
m_ssh_homedir.mkpath(".");
}
git_libgit2_init();
}
@ -26,7 +33,7 @@ Git::~Git()
bool Git::clone(QString url, QString path, cred_type mode)
{
if (!this->m_sem->tryAcquire(1, 500)) {
qWarning() << "Can acquire git semaphore a command is already running ";
qWarning() << "[Git] Can acquire git semaphore a command is already running ";
return false;
}
auto v = overload {
@ -44,18 +51,26 @@ bool Git::clone(QString url, QString path, cred_type mode)
bool Git::cloneHttp(QString url, QString path)
{
qInfo() << "Call clone command Http " << url << " " << path;
qInfo() << "[Git] Call clone command Http " << url << " " << path;
HTTP mode = {};
return this->clone(url, path, mode);
}
bool Git::cloneHttpPass(QString url, QString path, QString pass)
{
qInfo() << "Call clone command HttpPass " << url << " " << path;
qInfo() << "[Git] Call clone command HttpPass " << url << " " << path;
HTTPUserPass mode = { pass };
return this->clone(url, path, mode);
}
bool Git::cloneSshKey(QString url, QString path, QString passphrase)
{
qInfo() << "[Git] Call clone command HttpPass " << url << " " << path;
SSHKey mode = { this->pubKeyPath(), this->privKeyPath(), passphrase };
return this->clone(url, path, mode);
}
void Git::cloneResult(const bool err)
{
@ -66,3 +81,23 @@ void Git::cloneResult(const bool err)
}
this->m_sem->release();
}
bool Git::importSshKey(QUrl source_path, bool is_private){
auto destination_path = is_private ? this->privKeyPath() : this->pubKeyPath();
QFile source_file(source_path.toLocalFile());
if (!source_file.exists()) {
qWarning() << "[Git] Source file does not exist.";
return false;
}
QDir target_dir = QFileInfo(destination_path).absoluteDir();
if (!target_dir.exists()) {
if (!target_dir.mkpath(".")) {
qWarning() << "[Git] Failed to create target directory.";
return false;
}
}
return source_file.copy(destination_path);
}

View File

@ -2,6 +2,7 @@
#define GIT_H
#include "jobs/gitjob.h"
#include "qdebug.h"
#include <QUrl>
#include <QObject>
#include <QSemaphore>
@ -16,6 +17,8 @@
class Git : public QObject
{
Q_OBJECT
Q_PROPERTY(QString privKey READ pubKeyPath)
Q_PROPERTY(QString pubKey READ privKeyPath)
private slots:
/**
@ -47,6 +50,7 @@ signals:
private:
std::unique_ptr<QSemaphore> m_sem; /**< Semaphore for managing concurrent operations. */
QDir m_ssh_homedir; /**< Directory that contains the SSH keys (public and private). */
/**
* @brief Clones a repository from a specified URL.
@ -61,6 +65,27 @@ private:
*/
bool clone(QString url, QString path, cred_type mode);
protected:
/**
* @brief Get the path to the public keyring.
*
* @return The file path to the public key.
*/
QString pubKeyPath()
{
return this->m_ssh_homedir.filePath("id_rsa.pub");
}
/**
* @brief Get the path to the secret keyring.
*
* @return The file path to the private key.
*/
QString privKeyPath()
{
return this->m_ssh_homedir.filePath("id_rsa");
}
public:
/**
* @brief Constructor for the Git class.
@ -76,6 +101,9 @@ public:
*/
~Git() override;
Q_INVOKABLE bool importSshKey(QUrl source_path, bool is_private);
/**
* @brief Clones a repository over HTTP.
*
@ -97,13 +125,22 @@ public:
* @param url The HTTP URL of the Git repository to clone.
* @param path The destination path for the cloned repository.
* @param pass The password used for HTTP authentication.
* @return `true` if the clone operation was successful, `false` otherwise.
* @return `true` if the clone job operation was successfully started, `false` otherwise.
*/
Q_INVOKABLE bool cloneHttpPass(QString url, QString path, QString pass);
// Future SSH support methods:
// Q_INVOKABLE bool clone_ssh_pass(QString url, QString path, QString pass);
// Q_INVOKABLE bool clone_ssh_key(QString url, QString path, QString pub_key, QString priv_key, QString passphrase);
/**
* @brief Clones a repository over SSH with a key for authentication.
*
* This method clones a Git repository from the specified ssh URL using the provided password for authentication,
* and saves it to the given destination path.
*
* @param url The HTTP URL of the Git repository to clone.
* @param path The destination path for the cloned repository.
* @param passphrase The passphrase used for SSH authentication.
* @return `true` if the clone job operation was successfully started, `false` otherwise.
*/
Q_INVOKABLE bool cloneSshKey(QString url, QString path, QString passphrase);
// Q_INVOKABLE bool update(QUrl url, QString path);
// ....

View File

@ -18,17 +18,7 @@ GitJob::~GitJob()
git_libgit2_shutdown();
}
bool GitJob::getUsername(char **username, QString maybe_username, const char *username_from_url)
{
if (username_from_url) {
*username = strdup(username_from_url);
return true;
} else if (!maybe_username.isNull()) {
*username = maybe_username.toLocal8Bit().data();
return true;
}
return false;
}
int GitJob::credentialsCB(git_cred **out, const char *url, const char *username_from_url,
unsigned int allowed_types, void *payload)

View File

@ -1,6 +1,7 @@
#ifndef GITJOB_H
#define GITJOB_H
#include <QDir>
#include <QThread>
extern "C" {
#include <git2.h>

View File

@ -9,5 +9,4 @@ void GitPlugin::registerTypes(const char *uri)
{
//@uri Git
qmlRegisterSingletonType<Git>(uri, 1, 0, "Git", [](QQmlEngine *, QJSEngine *) -> QObject * { return new Git; });
}