Move UpdatePTUDevCtrl files into subdir UpdatePTUDevCtrl
This commit is contained in:
		
							
								
								
									
										434
									
								
								UpdatePTUDevCtrl/git/git_client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								UpdatePTUDevCtrl/git/git_client.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,434 @@
 | 
			
		||||
#include "git_client.h"
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GitClient::GitClient(QString const &customerNrStr,
 | 
			
		||||
                     QString const &customerRepository,
 | 
			
		||||
                     QString const &workingDirectory,
 | 
			
		||||
                     QString const &branchName,
 | 
			
		||||
                     QObject *parent)
 | 
			
		||||
  : QObject(parent)
 | 
			
		||||
  , m_worker(qobject_cast<Worker *>(parent))
 | 
			
		||||
  , m_repositoryPath(QString("https://git.mimbach49.de/GerhardHoffmann/%1.git").arg(customerNrStr))
 | 
			
		||||
  , m_customerNr(customerNrStr)
 | 
			
		||||
  , m_workingDirectory(workingDirectory)
 | 
			
		||||
  , m_branchName(branchName)
 | 
			
		||||
  , m_customerRepository(customerRepository) {
 | 
			
		||||
    if (!m_worker) {
 | 
			
		||||
        qCritical() << "ERROR CASTING PARENT TO WORKER FAILED";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitCloneCustomerRepository() {
 | 
			
		||||
    /*  Blobless clone
 | 
			
		||||
        ==============
 | 
			
		||||
 | 
			
		||||
        When using the --filter=blob:none option, the initial git clone will
 | 
			
		||||
        download all reachable commits and trees, and only download the blobs
 | 
			
		||||
        for commits when you do a git checkout. This includes the first checkout
 | 
			
		||||
        inside the git clone operation.
 | 
			
		||||
 | 
			
		||||
        The important thing to notice is that we have a copy of every blob at
 | 
			
		||||
        HEAD but the blobs in the history are not present. If your repository
 | 
			
		||||
        has a deep history full of large blobs, then this option can
 | 
			
		||||
        significantly reduce your git clone times. The commit and tree data is
 | 
			
		||||
        still present, so any subsequent git checkout only needs to download
 | 
			
		||||
        the missing blobs. The Git client knows how to batch these requests to
 | 
			
		||||
        ask the server only for the missing blobs.
 | 
			
		||||
 | 
			
		||||
        Further, when running git fetch in a blobless clone, the server only
 | 
			
		||||
        sends the new commits and trees. The new blobs are downloaded only
 | 
			
		||||
        after a git checkout. Note that git pull runs git fetch and then git
 | 
			
		||||
        merge, so it will download the necessary blobs during the git merge
 | 
			
		||||
        command.
 | 
			
		||||
 | 
			
		||||
        When using a blobless clone, you will trigger a blob download whenever
 | 
			
		||||
        you need the contents of a file, but you will not need one if you only
 | 
			
		||||
        need the OID (object-id) of a file. This means that git log can detect
 | 
			
		||||
        which commits changed a given path without needing to download extra
 | 
			
		||||
        data.
 | 
			
		||||
 | 
			
		||||
        This means that blobless clones can perform commands like git
 | 
			
		||||
        merge-base, git log, or even git log -- <path> with the same performance
 | 
			
		||||
        as a full clone.
 | 
			
		||||
 | 
			
		||||
        Commands like git diff or git blame <path> require the contents of the
 | 
			
		||||
        paths to compute diffs, so these will trigger blob downloads the first
 | 
			
		||||
        time they are run. However, the good news is that after that you will
 | 
			
		||||
        have those blobs in your repository and do not need to download them a
 | 
			
		||||
        second time. Most developers only need to run git blame on a small
 | 
			
		||||
        number of files, so this tradeoff of a slightly slower git blame command
 | 
			
		||||
        is worth the faster clone and fetch times.
 | 
			
		||||
 | 
			
		||||
        Note: git v2.18 does not support treeless clones: --filter=tree:0.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    // Note: for some reason it is necessary to pass "--progress ---v",
 | 
			
		||||
    // otherwise QProcess returns an error of 128 = 0x80 for the command.
 | 
			
		||||
 | 
			
		||||
    QString gitCommand("git clone --progress -vvv --filter=blob:none ");
 | 
			
		||||
    gitCommand += m_repositoryPath;
 | 
			
		||||
    Command c(gitCommand);
 | 
			
		||||
 | 
			
		||||
    qInfo() << "IN CURRENT WD" << m_workingDirectory
 | 
			
		||||
            << "CLONE VIA COMMAND" << gitCommand;
 | 
			
		||||
 | 
			
		||||
    if (c.execute(m_workingDirectory)) { // execute the command in wd
 | 
			
		||||
        QString const result = c.getCommandResult();
 | 
			
		||||
        if (!result.isEmpty()) {
 | 
			
		||||
            // Cloning into 'customer_281'...\n
 | 
			
		||||
            int customer = -1;
 | 
			
		||||
            int cloning = result.indexOf("Cloning", 0, Qt::CaseInsensitive);
 | 
			
		||||
            if (cloning != -1) {
 | 
			
		||||
                customer = result.indexOf("customer_", cloning, Qt::CaseInsensitive);
 | 
			
		||||
                if (customer != -1) {
 | 
			
		||||
                    QString customerNr = result.mid(customer);
 | 
			
		||||
                    static constexpr char const ch = '\'';
 | 
			
		||||
                    int i = customerNr.indexOf(QChar(ch));
 | 
			
		||||
                    if (i != -1) {
 | 
			
		||||
                        if ((customerNr = customerNr.mid(0, i)) == m_customerNr) {
 | 
			
		||||
                            qInfo() << "CLONING" << m_repositoryPath << "OK";
 | 
			
		||||
                            return true;
 | 
			
		||||
                        }
 | 
			
		||||
                        Utils::printCriticalErrorMsg(
 | 
			
		||||
                            QString("ERROR CLONE RESULT HAS WRONG CUSTOMER-NR. (%1 != %2) CLONE_RESULT=%3")
 | 
			
		||||
                                .arg(customerNr)
 | 
			
		||||
                                .arg(m_customerNr)
 | 
			
		||||
                                .arg(result));
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Utils::printCriticalErrorMsg(
 | 
			
		||||
                QString("ERROR CLONE RESULT HAS WRONG FORMAT. CLONING=%1 CUSTOMER=%2 CLONE_RESULT=%3")
 | 
			
		||||
                    .arg(cloning)
 | 
			
		||||
                    .arg(customer)
 | 
			
		||||
                    .arg(result));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        Utils::printCriticalErrorMsg("ERROR CLONE RESULT IS EMPTY");
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::copyGitConfigFromMaster() { // only allowed when called in
 | 
			
		||||
                                            // master branch (???)
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const cp = QString("cp .gitconfig .git/config");
 | 
			
		||||
        Command c("bash");
 | 
			
		||||
        if (c.execute(m_customerRepository, QStringList() << "-c" << cp)) {
 | 
			
		||||
            qInfo() << "cp .gitconfig .git/config OK";
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        qCritical() << "ERROR cp .gitconfig .git/config";
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList GitClient::gitBranchNames() {
 | 
			
		||||
    // git config --global pager.branch false
 | 
			
		||||
    QStringList bNames;
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString gitCommand("git branch -a");
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute(m_customerRepository)) {
 | 
			
		||||
            QString const result = c.getCommandResult();
 | 
			
		||||
            return result.split('\n');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return bNames;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitCheckoutBranch() {
 | 
			
		||||
    // TODO: nachsehen, ob der Branch ueberhaupt existiert
 | 
			
		||||
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        int zoneNr = Utils::read1stLineOfFile("/mnt/system_data/zone_nr");
 | 
			
		||||
        m_branchName = (zoneNr != 0)
 | 
			
		||||
            ? QString("zg1/zone%1").arg(zoneNr) : "master";
 | 
			
		||||
 | 
			
		||||
        QString gitCommand("git checkout ");
 | 
			
		||||
        gitCommand += m_branchName;
 | 
			
		||||
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        return c.execute(m_customerRepository); // execute command in customerRepo
 | 
			
		||||
    }
 | 
			
		||||
    Utils::printCriticalErrorMsg(QString("ERROR ") + m_customerRepository + " DOES NOT EXIST");
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitCloneAndCheckoutBranch() {
 | 
			
		||||
    qInfo() << "CLONE" << m_repositoryPath << "AND CHECKOUT" << m_branchName;
 | 
			
		||||
    if (gitCloneCustomerRepository()) {
 | 
			
		||||
        //if (copyGitConfigFromMaster()) {
 | 
			
		||||
            if (gitCheckoutBranch()) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else {
 | 
			
		||||
                // TODO
 | 
			
		||||
            }
 | 
			
		||||
        //}
 | 
			
		||||
    }
 | 
			
		||||
    Utils::printCriticalErrorMsg(QString("CLONE ") + m_repositoryPath + " AND CHECKOUT FAILED");
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList GitClient::gitShowReason(QString branchName) {
 | 
			
		||||
    QStringList lst;
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        // %h: commit (short form)
 | 
			
		||||
        // %s: commit message
 | 
			
		||||
        // %cI: commit date, strict ISO 8601 format
 | 
			
		||||
        // Note: branch with branchName has to exist: format zg1/zone1
 | 
			
		||||
        Command c(QString("git show origin/%1 -s --format=\"c=%h m=%s d=%cI\"").arg(branchName));
 | 
			
		||||
        if (c.execute(m_customerRepository)) {
 | 
			
		||||
            QString const s = c.getCommandResult().trimmed();
 | 
			
		||||
            int const c = s.indexOf("c=");
 | 
			
		||||
            int const m = s.indexOf("m=");
 | 
			
		||||
            int const d = s.indexOf("d=");
 | 
			
		||||
 | 
			
		||||
            QString msg = IsmasClient::getReasonForLastSendVersion();
 | 
			
		||||
            QString commit{""}, date{""};
 | 
			
		||||
 | 
			
		||||
            if (c != -1) {
 | 
			
		||||
                int start = c + 2;
 | 
			
		||||
                if (m >= start) {
 | 
			
		||||
                    int length = m - start;
 | 
			
		||||
                    commit = s.mid(start, length).trimmed();
 | 
			
		||||
 | 
			
		||||
                    start = m + 2;
 | 
			
		||||
                    if (d >= start) {
 | 
			
		||||
                        length = d - start;
 | 
			
		||||
                        msg += " (";
 | 
			
		||||
                        msg = s.mid(start, length).trimmed();
 | 
			
		||||
                        msg += ")";
 | 
			
		||||
 | 
			
		||||
                        start = d + 2;
 | 
			
		||||
                        date = s.mid(start);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!commit.isEmpty() && !msg.isEmpty() && !date.isEmpty()) {
 | 
			
		||||
                    lst << commit << msg << date;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << "CUSTOMER_REPOSITORY" << m_customerRepository
 | 
			
		||||
                    << "DOES NOT EXIST";
 | 
			
		||||
    }
 | 
			
		||||
    return lst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Zu beachten: wird eine datei neu hinzugefuegt (git add/commit) dann aber gleich
 | 
			
		||||
 wieder geloscht, so wird sie im diff nicht angezeigt.
 | 
			
		||||
 */
 | 
			
		||||
std::optional<QStringList> GitClient::gitDiff(QString const &commits) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        // 409f198..6c22726
 | 
			
		||||
        QString gitCommand("git diff --compact-summary ");
 | 
			
		||||
        gitCommand += commits;
 | 
			
		||||
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute(m_customerRepository)) { // execute command in local customerRepo
 | 
			
		||||
            QString s = c.getCommandResult().trimmed();
 | 
			
		||||
            Utils::printInfoMsg("GIT DIFF RESULT " + s);
 | 
			
		||||
 | 
			
		||||
            QStringList lines = Update::split(s, '\n');
 | 
			
		||||
            QStringList fileNames;
 | 
			
		||||
            // each line has the format "etc/psa_config/DC2C_print01.json | 1 +
 | 
			
		||||
            // or the format            "etc/psa_config/DC2C_print01.json (new) | 1 +
 | 
			
		||||
            // the filenames are relativ to the repository
 | 
			
		||||
            for (int i = 0; i < lines.size(); ++i) {
 | 
			
		||||
                QString const &line = lines.at(i);
 | 
			
		||||
                int newIndex = line.indexOf("(new");    // for new files
 | 
			
		||||
                int goneIndex = line.indexOf("(gone");  // for removed files
 | 
			
		||||
                int modeIndex = line.indexOf("(mode");
 | 
			
		||||
                int pipeIndex = line.indexOf('|');
 | 
			
		||||
                if (newIndex != -1) {
 | 
			
		||||
                    QString file = line.left(newIndex).trimmed();
 | 
			
		||||
                    qInfo() << "FILE (NEW)" << file;
 | 
			
		||||
                    fileNames << file;
 | 
			
		||||
                } else
 | 
			
		||||
                if (modeIndex != -1) {
 | 
			
		||||
                    QString const file = line.left(modeIndex).trimmed();
 | 
			
		||||
                    qInfo() << "FILE (MODE)" << file;
 | 
			
		||||
                    fileNames << file;
 | 
			
		||||
                } else
 | 
			
		||||
                if (goneIndex != -1) {
 | 
			
		||||
                    QString const file = line.left(goneIndex).trimmed();
 | 
			
		||||
                    qCritical() << "FILE (GONE)" << file;
 | 
			
		||||
                } else
 | 
			
		||||
                if (pipeIndex != -1) {
 | 
			
		||||
                    QString const file = line.left(pipeIndex).trimmed();
 | 
			
		||||
                    qInfo() << "FILE (PIPE)" << file;
 | 
			
		||||
                    fileNames << file;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!fileNames.isEmpty()) {
 | 
			
		||||
                return fileNames;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitFsck() {
 | 
			
		||||
    bool r = false;
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        Command c("git fsck");
 | 
			
		||||
        if ((r = c.execute(m_customerRepository)) == false) {
 | 
			
		||||
            QString const &s = c.getCommandResult().trimmed();
 | 
			
		||||
            Utils::printCriticalErrorMsg(QString("GIT FSCK FAILED: %1").arg(s));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 Hat sich nichts geaendert, so werden auch keine Commits <>..<> angezeigt
 | 
			
		||||
 */
 | 
			
		||||
std::optional<QString> GitClient::gitPull() {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        qInfo() << "BRANCH NAME" << m_branchName;
 | 
			
		||||
 | 
			
		||||
        Command c("git pull");
 | 
			
		||||
        if (c.execute(m_customerRepository)) {
 | 
			
		||||
            QString const s = c.getCommandResult().trimmed();
 | 
			
		||||
            if (!s.isEmpty()) {
 | 
			
		||||
                QStringList lines = Update::split(s, '\n');
 | 
			
		||||
                worker()->CONSOLE(lines) << Worker::UPDATE_STEP::UPDATE_REPOSITORY;
 | 
			
		||||
                if (!lines.empty()) {
 | 
			
		||||
                    static const QRegularExpression alreadyUpToDate("^\\s*Already\\s+up\\s+to\\s+date.*$");
 | 
			
		||||
                    if (std::none_of(lines.cbegin(), lines.cend(),
 | 
			
		||||
                        [](QString const &s) { return s.contains(alreadyUpToDate); })) {
 | 
			
		||||
                        int zoneNr = Utils::read1stLineOfFile("/mnt/system_data/zone_nr");
 | 
			
		||||
                        m_branchName = (zoneNr != 0) ? QString("zg1/zone%1").arg(zoneNr) : "master";
 | 
			
		||||
                        // lines can look like this:
 | 
			
		||||
                        // From https://git.mimbach49.de/GerhardHoffmann/customer_281
 | 
			
		||||
                        //   41ec581..5d25ac3  master     -> origin/master
 | 
			
		||||
                        //   ff10f57..43530a1  zg1/zone1  -> origin/zg1/zone1
 | 
			
		||||
                        //   6ed893f..5d9882c  zg1/zone2  -> origin/zg1/zone2
 | 
			
		||||
                        //   4384d17..77045d8  zg1/zone3  -> origin/zg1/zone3
 | 
			
		||||
                        //   89d2812..36a0d74  zg1/zone5  -> origin/zg1/zone5
 | 
			
		||||
                        bool found = false;
 | 
			
		||||
                        for (int i=0; i < lines.size(); ++i) {
 | 
			
		||||
                            if (lines.at(i).contains(m_branchName)) {
 | 
			
		||||
                                found = true;
 | 
			
		||||
                                // 409f198..6c22726  zg1/zone1  -> origin/zg1/zone1
 | 
			
		||||
                                static QRegularExpression re("(^\\s*)([0-9A-Fa-f]+..[0-9A-Fa-f]+)(.*$)");
 | 
			
		||||
                                QRegularExpressionMatch match = re.match(lines.at(i));
 | 
			
		||||
                                if (match.hasMatch()) {
 | 
			
		||||
                                    if (re.captureCount() == 3) { // start with full match (0), then the other 3 matches
 | 
			
		||||
                                        QString const matchCaptured = match.captured(2);
 | 
			
		||||
                                        worker()->CONSOLE(QStringList(matchCaptured)) << Worker::UPDATE_STEP::UPDATE_REPOSITORY;
 | 
			
		||||
                                        return matchCaptured;
 | 
			
		||||
                                    } else {
 | 
			
		||||
                                        QStringList lst(QString("(wrong capture count (%1)").arg(re.captureCount()));
 | 
			
		||||
                                        worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    QStringList lst("no regex-match for commits");
 | 
			
		||||
                                    worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        if (!found) {
 | 
			
		||||
                            QStringList lst(QString("unknown branch name ") + m_branchName);
 | 
			
		||||
                            worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return "Already up to date";
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    QStringList lst(QString("WRONG FORMAT FOR RESULT OF 'GIT PULL' ") + s);
 | 
			
		||||
                    worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                QStringList lst("EMPTY RESULT FOR 'GIT PULL'");
 | 
			
		||||
                worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        QStringList lst(QString("REPOSITORY ") + m_customerRepository + " DOES NOT EXIST");
 | 
			
		||||
        worker()->GUI(lst) << (worker()->CONSOLE(lst) << Worker::UPDATE_STEP::UPDATE_REPOSITORY_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<QStringList> GitClient::gitMerge() {
 | 
			
		||||
    Command c("git merge");
 | 
			
		||||
    if (c.execute(m_workingDirectory)) {
 | 
			
		||||
        QString s = c.getCommandResult();
 | 
			
		||||
        QStringList lst = Update::split(s, '\n');
 | 
			
		||||
        return lst;
 | 
			
		||||
    }
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString GitClient::gitLastCommit(QString fileName) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const filePath
 | 
			
		||||
            = QDir::cleanPath(m_customerRepository + QDir::separator() + fileName);
 | 
			
		||||
        if (QFile(filePath).exists()) {
 | 
			
		||||
            QString const gitCommand = QString("git log %1 | head -n 1").arg(fileName);
 | 
			
		||||
            Command c("bash");
 | 
			
		||||
            if (c.execute(m_customerRepository, QStringList() << "-c" << gitCommand)) {
 | 
			
		||||
                QString const r = c.getCommandResult();
 | 
			
		||||
                int const idx = r.indexOf("commit ");
 | 
			
		||||
                if (idx != -1) {
 | 
			
		||||
                    return r.mid(idx + 8).trimmed();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fileName has to an absolute path
 | 
			
		||||
QString GitClient::gitBlob(QString fileName) {
 | 
			
		||||
    QFileInfo fi(fileName);
 | 
			
		||||
    if (fi.exists()) {
 | 
			
		||||
        QString const gitCommand = QString("git hash-object %1").arg(fileName);
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute("/tmp")) {
 | 
			
		||||
            return c.getCommandResult().trimmed();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "N/A";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString GitClient::gitCommitForBlob(QString blob) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const gitCommand
 | 
			
		||||
            = QString("git whatchanged --all --find-object=%1 | head -n 1").arg(blob);
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        if (c.execute(m_customerRepository)) {
 | 
			
		||||
            return c.getCommandResult();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GitClient::gitIsFileTracked(QString fName) {
 | 
			
		||||
    if (QDir(m_customerRepository).exists()) {
 | 
			
		||||
        QString const gitCommand
 | 
			
		||||
            = QString("git ls-files --error-unmatch %1").arg(fName);
 | 
			
		||||
        Command c(gitCommand);
 | 
			
		||||
        return c.execute(m_customerRepository);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//get_commit_for_blob () {
 | 
			
		||||
//    # search for the blob in all commits for the file(name) $1
 | 
			
		||||
//    echo $(git log --all --pretty=format:%H -- $2   |
 | 
			
		||||
//           xargs -I{} bash -c "git ls-tree {} -- $2 |
 | 
			
		||||
//           grep -q $1 && echo -n {} && head -n 1")
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										62
									
								
								UpdatePTUDevCtrl/git/git_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								UpdatePTUDevCtrl/git/git_client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
#ifndef GIT_CLIENT_H_INCLUDED
 | 
			
		||||
#define GIT_CLIENT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
#include "process/command.h"
 | 
			
		||||
#include "ismas/ismas_client.h"
 | 
			
		||||
 | 
			
		||||
class Worker;
 | 
			
		||||
class GitClient : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    Worker *m_worker;
 | 
			
		||||
    QString const m_repositoryPath;
 | 
			
		||||
    QString const m_customerNr;
 | 
			
		||||
    QString const m_workingDirectory;
 | 
			
		||||
    QString m_branchName;
 | 
			
		||||
    QString const m_customerRepository;
 | 
			
		||||
 | 
			
		||||
    bool copyGitConfigFromMaster();
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit GitClient(QString const &customerNrStr,
 | 
			
		||||
                       QString const &repositoryPath,
 | 
			
		||||
                       QString const &workingDirectory = QCoreApplication::applicationDirPath(),
 | 
			
		||||
                       QString const &branchName = "master",
 | 
			
		||||
                       QObject *parent = 0);
 | 
			
		||||
 | 
			
		||||
    bool gitCloneCustomerRepository();
 | 
			
		||||
    bool gitCheckoutBranch();
 | 
			
		||||
    QStringList gitBranchNames();
 | 
			
		||||
 | 
			
		||||
    QString const workingDirectory() const { return m_workingDirectory; }
 | 
			
		||||
    QString workingDirectory() { return m_workingDirectory; }
 | 
			
		||||
 | 
			
		||||
    QString const branchName() const { return m_branchName; }
 | 
			
		||||
    QString branchName() { return m_branchName; }
 | 
			
		||||
 | 
			
		||||
    QString repositoryPath() { return m_repositoryPath; }
 | 
			
		||||
    QString const repositoryPath() const { return m_repositoryPath; }
 | 
			
		||||
 | 
			
		||||
    bool gitCloneAndCheckoutBranch();
 | 
			
		||||
 | 
			
		||||
    Worker *worker() { return m_worker; }
 | 
			
		||||
    Worker const *worker() const { return m_worker; }
 | 
			
		||||
 | 
			
		||||
    std::optional<QString> gitPull();
 | 
			
		||||
    std::optional<QStringList> gitDiff(QString const &commit);
 | 
			
		||||
    std::optional<QStringList> gitMerge();
 | 
			
		||||
 | 
			
		||||
    bool gitFsck();
 | 
			
		||||
 | 
			
		||||
    QString gitLastCommit(QString fileName);
 | 
			
		||||
    QStringList gitShowReason(QString branchName);
 | 
			
		||||
    static QString gitBlob(QString fileName);
 | 
			
		||||
    QString gitCommitForBlob(QString blob);
 | 
			
		||||
    bool gitIsFileTracked(QString file2name);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // GIT_CLIENT_H_INCLUDED
 | 
			
		||||
		Reference in New Issue
	
	Block a user