2023-07-10 15:57:17 +02:00
# include "git_client.h"
# include "update.h"
2023-07-14 13:16:01 +02:00
# include "worker.h"
2023-08-02 15:17:10 +02:00
# include "utils.h"
2023-07-10 15:57:17 +02:00
# include <QRegularExpression>
# include <QDebug>
# include <QDir>
2024-04-11 16:25:36 +02:00
# include <QStringList>
2023-07-10 15:57:17 +02:00
2024-06-28 10:03:10 +02:00
GitClient : : GitClient ( QString const & customerRepositoryPath ,
QString const & customerNrStr ,
2023-07-17 16:49:44 +02:00
QString const & customerRepository ,
2023-07-14 13:16:01 +02:00
QString const & workingDirectory ,
QString const & branchName ,
QObject * parent )
: QObject ( parent )
, m_worker ( qobject_cast < Worker * > ( parent ) )
2024-06-28 10:03:10 +02:00
, m_repositoryPath ( customerRepositoryPath )
2023-07-17 16:49:44 +02:00
, m_customerNr ( customerNrStr )
2023-07-14 13:16:01 +02:00
, m_workingDirectory ( workingDirectory )
, m_branchName ( branchName )
2023-07-17 16:49:44 +02:00
, m_customerRepository ( customerRepository ) {
2023-07-14 13:16:01 +02:00
if ( ! m_worker ) {
qCritical ( ) < < " ERROR CASTING PARENT TO WORKER FAILED " ;
}
2023-07-10 15:57:17 +02:00
}
2023-07-14 13:16:01 +02:00
bool GitClient : : gitCloneCustomerRepository ( ) {
2023-10-18 11:36:13 +02:00
/* 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.
*/
2023-10-19 13:35:07 +02:00
// 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 " ) ;
2023-07-14 13:16:01 +02:00
gitCommand + = m_repositoryPath ;
2023-07-10 15:57:17 +02:00
Command c ( gitCommand ) ;
2023-07-14 13:16:01 +02:00
qInfo ( ) < < " IN CURRENT WD " < < m_workingDirectory
2023-10-18 11:36:13 +02:00
< < " CLONE VIA COMMAND " < < gitCommand ;
2023-07-14 13:16:01 +02:00
if ( c . execute ( m_workingDirectory ) ) { // execute the command in wd
2023-07-19 16:50:54 +02:00
QString const result = c . getCommandResult ( ) ;
2023-07-10 15:57:17 +02:00
if ( ! result . isEmpty ( ) ) {
// Cloning into 'customer_281'...\n
2023-10-19 13:35:07 +02:00
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 ;
2023-07-14 13:16:01 +02:00
}
2023-07-10 15:57:17 +02:00
}
}
2023-10-18 11:36:13 +02:00
Utils : : printCriticalErrorMsg (
2023-10-19 13:35:07 +02:00
QString ( " ERROR CLONE RESULT HAS WRONG FORMAT. CLONING=%1 CUSTOMER=%2 CLONE_RESULT=%3 " )
. arg ( cloning )
. arg ( customer )
2023-10-18 11:36:13 +02:00
. arg ( result ) ) ;
return false ;
2023-07-10 15:57:17 +02:00
}
2023-10-18 11:36:13 +02:00
Utils : : printCriticalErrorMsg ( " ERROR CLONE RESULT IS EMPTY " ) ;
2023-07-10 15:57:17 +02:00
}
2023-07-14 13:16:01 +02:00
return false ;
2023-07-10 15:57:17 +02:00
}
2023-07-14 13:16:01 +02:00
bool GitClient : : copyGitConfigFromMaster ( ) { // only allowed when called in
2023-07-17 16:49:44 +02:00
// master branch (???)
2023-07-14 13:16:01 +02:00
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 ;
2023-07-10 15:57:17 +02:00
}
2023-08-02 15:17:10 +02:00
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 ;
}
2023-07-14 13:16:01 +02:00
bool GitClient : : gitCheckoutBranch ( ) {
2023-08-02 15:17:10 +02:00
// TODO: nachsehen, ob der Branch ueberhaupt existiert
2023-07-14 13:16:01 +02:00
if ( QDir ( m_customerRepository ) . exists ( ) ) {
2023-08-04 13:33:25 +02:00
int zoneNr = Utils : : read1stLineOfFile ( " /mnt/system_data/zone_nr " ) ;
2023-08-02 15:17:10 +02:00
m_branchName = ( zoneNr ! = 0 )
? QString ( " zg1/zone%1 " ) . arg ( zoneNr ) : " master " ;
2023-07-14 13:16:01 +02:00
QString gitCommand ( " git checkout " ) ;
gitCommand + = m_branchName ;
2023-08-02 15:17:10 +02:00
2023-07-14 13:16:01 +02:00
Command c ( gitCommand ) ;
return c . execute ( m_customerRepository ) ; // execute command in customerRepo
}
2023-08-11 11:11:14 +02:00
Utils : : printCriticalErrorMsg ( QString ( " ERROR " ) + m_customerRepository + " DOES NOT EXIST " ) ;
2023-07-14 13:16:01 +02:00
return false ;
}
bool GitClient : : gitCloneAndCheckoutBranch ( ) {
qInfo ( ) < < " CLONE " < < m_repositoryPath < < " AND CHECKOUT " < < m_branchName ;
if ( gitCloneCustomerRepository ( ) ) {
2023-07-17 16:49:44 +02:00
//if (copyGitConfigFromMaster()) {
2023-07-19 16:50:54 +02:00
if ( gitCheckoutBranch ( ) ) {
return true ;
} else {
2023-08-02 15:17:10 +02:00
// TODO
2023-07-19 16:50:54 +02:00
}
2023-07-17 16:49:44 +02:00
//}
2023-07-10 15:57:17 +02:00
}
2023-08-11 11:11:14 +02:00
Utils : : printCriticalErrorMsg ( QString ( " CLONE " ) + m_repositoryPath + " AND CHECKOUT FAILED " ) ;
2023-07-14 13:16:01 +02:00
return false ;
2023-07-10 15:57:17 +02:00
}
2023-10-09 15:53:35 +02:00
QStringList GitClient : : gitShowReason ( QString branchName ) {
2023-08-16 10:33:08 +02:00
QStringList lst ;
if ( QDir ( m_customerRepository ) . exists ( ) ) {
// %h: commit (short form)
// %s: commit message
// %cI: commit date, strict ISO 8601 format
2023-10-09 15:53:35 +02:00
// 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 ) ) ;
2023-08-16 10:33:08 +02:00
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= " ) ;
2023-09-04 11:46:37 +02:00
2024-04-29 15:03:43 +02:00
QString msg { " " } ; // IsmasClient::getReasonForLastSendVersion();
2023-09-04 11:46:37 +02:00
QString commit { " " } , date { " " } ;
2023-08-16 10:33:08 +02:00
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 ;
2024-04-29 15:03:43 +02:00
// msg = " (";
2023-08-16 10:33:08 +02:00
msg = s . mid ( start , length ) . trimmed ( ) ;
2024-04-29 15:03:43 +02:00
// msg += ")";
2023-08-16 10:33:08 +02:00
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 ;
}
2023-07-14 13:16:01 +02:00
/*
Zu beachten : wird eine datei neu hinzugefuegt ( git add / commit ) dann aber gleich
wieder geloscht , so wird sie im diff nicht angezeigt .
*/
2023-07-10 15:57:17 +02:00
std : : optional < QStringList > GitClient : : gitDiff ( QString const & commits ) {
2023-07-14 13:16:01 +02:00
if ( QDir ( m_customerRepository ) . exists ( ) ) {
// 409f198..6c22726
QString gitCommand ( " git diff --compact-summary " ) ;
gitCommand + = commits ;
2023-07-10 15:57:17 +02:00
2023-07-14 13:16:01 +02:00
Command c ( gitCommand ) ;
if ( c . execute ( m_customerRepository ) ) { // execute command in local customerRepo
QString s = c . getCommandResult ( ) . trimmed ( ) ;
2023-08-11 11:11:14 +02:00
Utils : : printInfoMsg ( " GIT DIFF RESULT " + s ) ;
2023-08-09 16:12:56 +02:00
2023-08-11 11:12:09 +02:00
QStringList lines = Update : : split ( s , ' \n ' ) ;
2023-07-14 13:16:01 +02:00
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 ) {
2023-08-09 16:12:56 +02:00
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 " ) ;
2023-08-11 11:12:09 +02:00
int pipeIndex = line . indexOf ( ' | ' ) ;
2023-07-14 13:16:01 +02:00
if ( newIndex ! = - 1 ) {
2023-08-09 16:12:56 +02:00
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 ;
2023-08-11 11:12:09 +02:00
} else
if ( pipeIndex ! = - 1 ) {
QString const file = line . left ( pipeIndex ) . trimmed ( ) ;
qInfo ( ) < < " FILE (PIPE) " < < file ;
fileNames < < file ;
2023-07-10 15:57:17 +02:00
}
}
2023-07-14 13:16:01 +02:00
if ( ! fileNames . isEmpty ( ) ) {
return fileNames ;
}
2023-07-10 15:57:17 +02:00
}
}
return std : : nullopt ;
}
2023-10-20 13:55:18 +02:00
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 ;
}
2024-04-11 16:25:36 +02:00
bool GitClient : : branchExistsRemotely ( ) {
bool remoteBranchExists = false ;
if ( QDir ( m_customerRepository ) . exists ( ) ) {
qInfo ( ) < < " BRANCH NAME " < < m_branchName ;
QString const cmd = QString ( " git ls-remote --exit-code --heads origin %1 " ) . arg ( m_branchName ) ;
Command c ( cmd ) ;
if ( c . execute ( m_customerRepository ) ) {
// expected result: c16c833c8778c1b3691a74afee5a469177e4e69b refs/heads/zg1/zone1000
QString const s = c . getCommandResult ( ) . trimmed ( ) ;
if ( ! s . isEmpty ( ) ) {
// the result is only one line
if ( ( remoteBranchExists = s . contains ( m_branchName ) ) = = true ) {
qCritical ( ) < < " ( " < < __func__ < < " : " < < __LINE__ < < " ) branch "
< < m_branchName < < " EXISTS REMOTELY. ( " < < s < < " ) " ;
}
} else {
Utils : : printCriticalErrorMsg ( QString ( " EMPTY RESULT FOR CMD %1 " ) . arg ( cmd ) ) ;
}
} else {
Utils : : printCriticalErrorMsg ( QString ( " FAILED TO EXEC '%1' " ) . arg ( cmd ) ) ;
}
}
return remoteBranchExists ;
}
bool GitClient : : branchExistsLocally ( ) {
Command c ( " git branch -l " ) ;
if ( c . execute ( m_customerRepository ) ) {
QString const s = c . getCommandResult ( ) . trimmed ( ) ;
if ( ! s . isEmpty ( ) ) {
QStringList lines = Update : : split ( s , ' \n ' ) ;
if ( ! lines . empty ( ) ) {
for ( int i = 0 ; i < lines . size ( ) ; + + i ) {
QString line = lines . at ( i ) ;
// expected: * [new branch] zg1/zone12 -> origin/zg1/zone12"
if ( line . contains ( m_branchName ) ) {
if ( m_worker ) {
QStringList lst ( QString ( " BRANCH-NAME %1 CONTAINED IN RESULT %2 " ) . arg ( m_branchName ) . arg ( s ) ) ;
m_worker - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : PULL_NEW_BRANCH ;
}
return true ;
}
}
if ( m_worker ) {
QStringList lst ( QString ( " BRANCH-NAME %1 NOT CONTAINED IN RESULT %2 " ) . arg ( m_branchName ) . arg ( s ) ) ;
m_worker - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : PULL_NEW_BRANCH_FAILURE ;
}
} else {
if ( m_worker ) {
QStringList lst ( QString ( " 'git branch -l' RETURNED NO LINES " ) ) ;
m_worker - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : PULL_NEW_BRANCH_FAILURE ;
}
}
} else {
if ( m_worker ) {
QStringList lst ( QString ( " 'git branch -l' RETURNED EMPTY RESULT " ) ) ;
m_worker - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : PULL_NEW_BRANCH_FAILURE ;
}
}
} else {
if ( m_worker ) {
QStringList lst ( QString ( " FAILED TO EXEC 'git branch -l' " ) ) ;
m_worker - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : PULL_NEW_BRANCH_FAILURE ;
}
}
return false ;
}
bool GitClient : : gitPullNewBranches ( ) {
if ( QDir ( m_customerRepository ) . exists ( ) ) {
Command c ( " git pull " ) ;
if ( c . execute ( m_customerRepository ) ) {
QString const s = c . getCommandResult ( ) . trimmed ( ) ;
// expected: Already up-to-date.
if ( ! s . isEmpty ( ) ) {
QStringList lst ;
QString msg ( QString ( " GIT-PULL-NEW-BRANCH. RESULT=%1 " ) . arg ( s ) ) ;
if ( m_worker ) {
m_worker - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : PULL_NEW_BRANCH ;
}
return true ;
}
}
}
return false ;
}
2023-07-14 13:16:01 +02:00
/*
Hat sich nichts geaendert , so werden auch keine Commits < > . . < > angezeigt
*/
2023-10-18 11:37:46 +02:00
std : : optional < QString > GitClient : : gitPull ( ) {
2023-07-17 16:49:44 +02:00
if ( QDir ( m_customerRepository ) . exists ( ) ) {
2023-08-09 15:03:14 +02:00
qInfo ( ) < < " BRANCH NAME " < < m_branchName ;
2023-08-02 15:17:10 +02:00
2024-10-23 12:58:48 +02:00
#if 0
IMPORTANT COMMENT :
If remote host keys are changed , then
export GIT_SSH_COMMAND = " ssh -i /opt/app/tools/atbupdate/.keys/id_ed25519_ptuConfig "
git pull
leads to the following warning / error message :
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
@ WARNING : REMOTE HOST IDENTIFICATION HAS CHANGED ! @
@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY !
Someone could be eavesdropping on you right now ( man - in - the - middle attack ) !
It is also possible that a host key has just been changed .
The fingerprint for the ECDSA key sent by the remote host is
SHA256 : vOD5jF2hglGktqLhK9ABxfEjwEgIK68 / v9erdT05NDQ .
Please contact your system administrator .
Add correct host key in / home / root / . ssh / known_hosts to get rid of this message .
Offending ECDSA key in / home / root / . ssh / known_hosts : 1
Password authentication is disabled to avoid man - in - the - middle attacks .
Keyboard - interactive authentication is disabled to avoid man - in - the - middle attacks .
Agent forwarding is disabled to avoid man - in - the - middle attacks .
X11 forwarding is disabled to avoid man - in - the - middle attacks .
Already up to date .
2024-10-23 13:22:42 +02:00
This first part is from ssh itself . Only the last line is the git message .
2024-10-23 12:58:48 +02:00
2024-10-23 13:22:42 +02:00
Here an output of running ATBUpdateTool with a corrupted known - hosts - file :
. . .
Oct 23 14 : 18 : 18 ATB_PTU5 ATBUpdateTool [ 2696 ] : ( branchExistsRemotely : 310 ) branch " zg1/zone1 " EXISTS REMOTELY . ( " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \r \n @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ \r \n @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \r \n IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! \r \n Someone could be eavesdropping on you right now (man-in-the-middle attack)! \r \n It is also possible that a host key has just been changed. \r \n The fingerprint for the ECDSA key sent by the remote host is \n SHA256:vOD5jF2hglGktqLhK9ABxfEjwEgIK68/v9erdT05NDQ. \r \n Please contact your system administrator. \r \n Add correct host key in /home/root/.ssh/known_hosts to get rid of this message. \r \n Offending ECDSA key in /home/root/.ssh/known_hosts:1 \r \n Password authentication is disabled to avoid man-in-the-middle attacks. \r \n Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks. \r \n Agent forwarding is disabled to avoid man-in-the-middle attacks. \r \n X11 forwarding is disabled to avoid man-in-the-middle attacks. \r \n bd4e8da4780b1a7d6be3d3ce8419f43ccf7e706f \t refs/heads/zg1/zone1 " )
Oct 23 14 : 18 : 18 ATB_PTU5 ATBUpdateTool [ 2696 ] : EXECUTED " git branch -l " " (runtime 16ms) " with code 0 IN " /opt/app/tools/atbupdate/customer_336 "
Oct 23 14 : 18 : 18 ATB_PTU5 ATBUpdateTool [ 2696 ] : " UPDATE_STEP::PULL_NEW_BRANCH "
Oct 23 14 : 18 : 18 ATB_PTU5 ATBUpdateTool [ 2696 ] : " BRANCH-NAME zg1/zone1 CONTAINED IN RESULT master \n * zg1/zone1 " . . . . .
The download continues .
2024-10-23 12:58:48 +02:00
# endif
2023-10-18 11:37:46 +02:00
Command c ( " git pull " ) ;
2023-07-17 16:49:44 +02:00
if ( c . execute ( m_customerRepository ) ) {
2023-07-14 13:16:01 +02:00
QString const s = c . getCommandResult ( ) . trimmed ( ) ;
if ( ! s . isEmpty ( ) ) {
QStringList lines = Update : : split ( s , ' \n ' ) ;
2023-10-30 15:00:57 +01:00
worker ( ) - > CONSOLE ( lines ) < < Worker : : UPDATE_STEP : : UPDATE_REPOSITORY ;
2023-07-14 13:16:01 +02:00
if ( ! lines . empty ( ) ) {
2023-10-30 14:59:58 +01:00
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
2024-04-09 14:49:42 +02:00
//
// More exactly:
// remote: Counting objects: 382, done.
// remote: Compressing objects: 100% (203/203), done.
// remote: Total 278 (delta 177), reused 103 (delta 59)
// Receiving objects: 100% (278/278), 4.89 MiB | 539 KiB/s, done.
// Resolving deltas: 100% (177/177), completed with 40 local objects.
// From ssh://longair@pacific.mpi-cbg.de/srv/git/fiji
// 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030
// * [new branch] debian-release-20081112 -> origin/debian-release-20081112
// * [new branch] debian-release-20081112.1 -> origin/debian-release-20081112.1
// 3d619e7..6260626 master -> origin/master
//
// The most important bits here are the lines like these:
//
// 3036acc..9eb5e40 debian-release-20081030 -> origin/debian-release-20081030
// * [new branch] debian-release-20081112 -> origin/debian-release-20081112
//
// The first line of these two shows that your remote-tracking branch
// origin/debian-release-20081030 has been advanced from the commit 3036acc to 9eb5e40.
// The bit before the arrow is the name of the branch in the remote repository.
// The second line similarly show that since we last did this, a new remote tracking
// branch has been created. (git fetch may also fetch new tags if they have appeared
// in the remote repository.)
2023-10-30 14:59:58 +01:00
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 - 9 A - Fa - f ] + . . [ 0 - 9 A - 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 ) ;
}
2023-08-04 13:35:42 +02:00
} else {
2023-10-30 15:00:57 +01:00
QStringList lst ( " no regex-match for commits " ) ;
worker ( ) - > GUI ( lst ) < < ( worker ( ) - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : UPDATE_REPOSITORY_FAILURE ) ;
2023-08-04 13:35:42 +02:00
}
}
2023-07-14 13:16:01 +02:00
}
2023-10-30 15:00:57 +01:00
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 " ;
2023-07-14 13:16:01 +02:00
}
} else {
2023-10-30 15:00:57 +01:00
QStringList lst ( QString ( " WRONG FORMAT FOR RESULT OF 'GIT PULL' " ) + s ) ;
worker ( ) - > GUI ( lst ) < < ( worker ( ) - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : UPDATE_REPOSITORY_FAILURE ) ;
2023-07-10 15:57:17 +02:00
}
2023-07-14 13:16:01 +02:00
} else {
2023-10-30 15:00:57 +01:00
QStringList lst ( " EMPTY RESULT FOR 'GIT PULL' " ) ;
worker ( ) - > GUI ( lst ) < < ( worker ( ) - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : UPDATE_REPOSITORY_FAILURE ) ;
2023-07-10 15:57:17 +02:00
}
}
2023-07-14 13:16:01 +02:00
} else {
2023-10-30 15:00:57 +01:00
QStringList lst ( QString ( " REPOSITORY " ) + m_customerRepository + " DOES NOT EXIST " ) ;
worker ( ) - > GUI ( lst ) < < ( worker ( ) - > CONSOLE ( lst ) < < Worker : : UPDATE_STEP : : UPDATE_REPOSITORY_FAILURE ) ;
2023-07-10 15:57:17 +02:00
}
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 ;
}
2023-07-14 13:16:01 +02:00
QString GitClient : : gitLastCommit ( QString fileName ) {
if ( QDir ( m_customerRepository ) . exists ( ) ) {
QString const filePath
= QDir : : cleanPath ( m_customerRepository + QDir : : separator ( ) + fileName ) ;
2023-08-11 11:12:59 +02:00
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 ( ) ;
}
2023-07-14 13:16:01 +02:00
}
}
}
return " " ;
}
2023-07-19 16:50:54 +02:00
// fileName has to an absolute path
2023-07-14 13:16:01 +02:00
QString GitClient : : gitBlob ( QString fileName ) {
2023-07-19 16:50:54 +02:00
QFileInfo fi ( fileName ) ;
if ( fi . exists ( ) ) {
2023-07-14 13:16:01 +02:00
QString const gitCommand = QString ( " git hash-object %1 " ) . arg ( fileName ) ;
Command c ( gitCommand ) ;
2023-08-22 12:19:25 +02:00
if ( c . execute ( " /tmp " ) ) {
2023-07-19 16:50:54 +02:00
return c . getCommandResult ( ) . trimmed ( ) ;
2023-07-14 13:16:01 +02:00
}
}
2023-07-19 16:50:54 +02:00
return " N/A " ;
2023-07-14 13:16:01 +02:00
}
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")
//}