| 1 | #include "gitmanager.h" | 
|---|
| 2 | #include "../utils.h" | 
|---|
| 3 | #include "../settings.h" | 
|---|
| 4 |  | 
|---|
| 5 | #include <QDir> | 
|---|
| 6 | #include <QFileInfo> | 
|---|
| 7 |  | 
|---|
| 8 | GitManager::GitManager(QObject *parent) : QObject(parent) | 
|---|
| 9 | { | 
|---|
| 10 | } | 
|---|
| 11 |  | 
|---|
| 12 | void GitManager::createRepository(const QString &folder) | 
|---|
| 13 | { | 
|---|
| 14 | QString currentBranch; | 
|---|
| 15 | if (hasRepository(folder,currentBranch)) | 
|---|
| 16 | throw GitError(tr( "Folder \"%1\" already has a repository!")); | 
|---|
| 17 | QStringList args; | 
|---|
| 18 | args.append( "init"); | 
|---|
| 19 | runGit(folder,args); | 
|---|
| 20 |  | 
|---|
| 21 | QStringList contents; | 
|---|
| 22 | contents.append( ".git"); | 
|---|
| 23 | contents.append( "*.o"); | 
|---|
| 24 | contents.append( "*.exe"); | 
|---|
| 25 | contents.append( "*.layout"); | 
|---|
| 26 | #ifdef Q_OS_LINUX | 
|---|
| 27 | contents.append( "*."); | 
|---|
| 28 | #endif | 
|---|
| 29 |  | 
|---|
| 30 | QDir dir(folder); | 
|---|
| 31 | stringsToFile(contents,dir.filePath( ".gitignore")); | 
|---|
| 32 | QString output; | 
|---|
| 33 | add(folder, ".gitignore",output); | 
|---|
| 34 | } | 
|---|
| 35 |  | 
|---|
| 36 | bool GitManager::hasRepository(const QString &folder, QString& currentBranch) | 
|---|
| 37 | { | 
|---|
| 38 | if (folder.isEmpty()) | 
|---|
| 39 | return false; | 
|---|
| 40 | QStringList args; | 
|---|
| 41 | args.append( "status"); | 
|---|
| 42 | args.append( "-b"); | 
|---|
| 43 | args.append( "-u"); | 
|---|
| 44 | args.append( "no"); | 
|---|
| 45 | args.append( "--ignored=no"); | 
|---|
| 46 | QString output = runGit(folder,args); | 
|---|
| 47 | bool result = output.startsWith( "On branch"); | 
|---|
| 48 | if (result) { | 
|---|
| 49 | int pos = QString( "On branch").length(); | 
|---|
| 50 | while (pos<output.length() && output[pos].isSpace()) | 
|---|
| 51 | pos++; | 
|---|
| 52 | int endPos = pos; | 
|---|
| 53 | while (endPos<output.length() && !output[endPos].isSpace()) | 
|---|
| 54 | endPos++; | 
|---|
| 55 | currentBranch = output.mid(pos,endPos-pos); | 
|---|
| 56 | } | 
|---|
| 57 | return result; | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | QString GitManager::rootFolder(const QString &folder) | 
|---|
| 61 | { | 
|---|
| 62 | QStringList args; | 
|---|
| 63 | args.append( "rev-parse"); | 
|---|
| 64 | args.append( "--show-toplevel"); | 
|---|
| 65 | return runGit(folder,args).trimmed(); | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | bool GitManager::isFileInRepository(const QFileInfo& fileInfo) | 
|---|
| 69 | { | 
|---|
| 70 | QStringList args; | 
|---|
| 71 | args.append( "ls-files"); | 
|---|
| 72 | args.append(fileInfo.fileName()); | 
|---|
| 73 | QString output = runGit(fileInfo.absolutePath(),args); | 
|---|
| 74 | return output.trimmed() == fileInfo.fileName(); | 
|---|
| 75 | } | 
|---|
| 76 |  | 
|---|
| 77 | bool GitManager::isFileStaged(const QFileInfo &fileInfo) | 
|---|
| 78 | { | 
|---|
| 79 | QStringList args; | 
|---|
| 80 | args.append( "diff"); | 
|---|
| 81 | args.append( "--staged"); | 
|---|
| 82 | args.append( "--name-only"); | 
|---|
| 83 | args.append(fileInfo.fileName()); | 
|---|
| 84 | QString output = runGit(fileInfo.absolutePath(),args); | 
|---|
| 85 | return output.trimmed() == fileInfo.fileName(); | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | bool GitManager::isFileChanged(const QFileInfo &fileInfo) | 
|---|
| 89 | { | 
|---|
| 90 | QStringList args; | 
|---|
| 91 | args.append( "diff"); | 
|---|
| 92 | args.append( "--name-only"); | 
|---|
| 93 | args.append(fileInfo.fileName()); | 
|---|
| 94 | QString output = runGit(fileInfo.absolutePath(),args); | 
|---|
| 95 | return output.trimmed() == fileInfo.fileName(); | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | bool GitManager::add(const QString &folder, const QString &path, QString& output) | 
|---|
| 99 | { | 
|---|
| 100 | QStringList args; | 
|---|
| 101 | args.append( "add"); | 
|---|
| 102 | args.append(path); | 
|---|
| 103 | output = runGit(folder,args); | 
|---|
| 104 | return isSuccess(output); | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | bool GitManager::remove(const QString &folder, const QString &path, QString& output) | 
|---|
| 108 | { | 
|---|
| 109 | QStringList args; | 
|---|
| 110 | args.append( "rm"); | 
|---|
| 111 | args.append(path); | 
|---|
| 112 | output = runGit(folder,args); | 
|---|
| 113 | return isSuccess(output); | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | bool GitManager::rename(const QString &folder, const QString &oldName, | 
|---|
| 117 | const QString &newName, QString& output) | 
|---|
| 118 | { | 
|---|
| 119 | QStringList args; | 
|---|
| 120 | args.append( "mv"); | 
|---|
| 121 | args.append(oldName); | 
|---|
| 122 | args.append(newName); | 
|---|
| 123 | output = runGit(folder,args); | 
|---|
| 124 | return isSuccess(output); | 
|---|
| 125 | } | 
|---|
| 126 |  | 
|---|
| 127 | bool GitManager::restore(const QString &folder, const QString &path, QString& output) | 
|---|
| 128 | { | 
|---|
| 129 | QStringList args; | 
|---|
| 130 | args.append( "restore"); | 
|---|
| 131 | if (path.isEmpty()) | 
|---|
| 132 | args.append( "."); | 
|---|
| 133 | else | 
|---|
| 134 | args.append(path); | 
|---|
| 135 | output = runGit(folder,args); | 
|---|
| 136 | return isSuccess(output); | 
|---|
| 137 | } | 
|---|
| 138 |  | 
|---|
| 139 | int GitManager::logCounts(const QString &folder, const QString &branch) | 
|---|
| 140 | { | 
|---|
| 141 | QStringList args; | 
|---|
| 142 | args.append( "rev-list"); | 
|---|
| 143 | args.append( "--count"); | 
|---|
| 144 | if (branch.isEmpty()) | 
|---|
| 145 | args.append( "HEAD"); | 
|---|
| 146 | else | 
|---|
| 147 | args.append(branch); | 
|---|
| 148 | QString s = runGit(folder,args).trimmed(); | 
|---|
| 149 | bool ok; | 
|---|
| 150 | int result = s.toInt(&ok); | 
|---|
| 151 | if (!ok) | 
|---|
| 152 | result = 0; | 
|---|
| 153 | return result; | 
|---|
| 154 | } | 
|---|
| 155 |  | 
|---|
| 156 | QList<PGitCommitInfo> GitManager::log(const QString &folder, int start, int count, const QString &branch) | 
|---|
| 157 | { | 
|---|
| 158 | QStringList args; | 
|---|
| 159 | args.append( "log"); | 
|---|
| 160 | args.append( "--skip"); | 
|---|
| 161 | args.append(QString( "%1").arg(start)); | 
|---|
| 162 | args.append( "-n"); | 
|---|
| 163 | args.append(QString( "%1").arg(count)); | 
|---|
| 164 | args.append( "--format=medium"); | 
|---|
| 165 | args.append( "--date=iso-strict"); | 
|---|
| 166 | if (branch.isEmpty()) | 
|---|
| 167 | args.append( "HEAD"); | 
|---|
| 168 | else | 
|---|
| 169 | args.append(branch); | 
|---|
| 170 | QString output = runGit(folder,args); | 
|---|
| 171 | QStringList lines = textToLines(output); | 
|---|
| 172 | QList<PGitCommitInfo> result; | 
|---|
| 173 | int pos = 0; | 
|---|
| 174 | PGitCommitInfo commitInfo; | 
|---|
| 175 | while (pos<lines.length()) { | 
|---|
| 176 | if (lines[pos].startsWith( "commit ")) { | 
|---|
| 177 | commitInfo = std::make_shared<GitCommitInfo>(); | 
|---|
| 178 | commitInfo->commitHash=lines[pos].mid(QString( "commit ").length()).trimmed(); | 
|---|
| 179 | result.append(commitInfo); | 
|---|
| 180 | } else if(!commitInfo) { | 
|---|
| 181 | break; | 
|---|
| 182 | } else if (lines[pos].startsWith( "Author:")) { | 
|---|
| 183 | commitInfo->author=lines[pos].mid(QString( "Author:").length()).trimmed(); | 
|---|
| 184 | } else if (lines[pos].startsWith( "Date:")) { | 
|---|
| 185 | commitInfo->authorDate=QDateTime::fromString(lines[pos].mid(QString( "Date:").length()).trimmed(),Qt::ISODate); | 
|---|
| 186 | } else if (!lines[pos].trimmed().isEmpty()) { | 
|---|
| 187 | if (commitInfo->title.isEmpty()) { | 
|---|
| 188 | commitInfo->title = lines[pos].trimmed(); | 
|---|
| 189 | } else { | 
|---|
| 190 | commitInfo->fullCommitMessage.append(lines[pos].trimmed()+ "\n"); | 
|---|
| 191 | } | 
|---|
| 192 | } | 
|---|
| 193 | pos++; | 
|---|
| 194 | } | 
|---|
| 195 | return result; | 
|---|
| 196 | } | 
|---|
| 197 |  | 
|---|
| 198 | QStringList GitManager::listFiles(const QString &folder) | 
|---|
| 199 | { | 
|---|
| 200 | QStringList args; | 
|---|
| 201 | args.append( "ls-files"); | 
|---|
| 202 | return textToLines(runGit(folder,args)); | 
|---|
| 203 | } | 
|---|
| 204 |  | 
|---|
| 205 | QStringList GitManager::listStagedFiles(const QString &folder) | 
|---|
| 206 | { | 
|---|
| 207 | QStringList args; | 
|---|
| 208 | args.append( "diff"); | 
|---|
| 209 | args.append( "--staged"); | 
|---|
| 210 | args.append( "--name-only"); | 
|---|
| 211 | return textToLines(runGit(folder,args)); | 
|---|
| 212 | } | 
|---|
| 213 |  | 
|---|
| 214 | QStringList GitManager::listChangedFiles(const QString &folder) | 
|---|
| 215 | { | 
|---|
| 216 | QStringList args; | 
|---|
| 217 | args.append( "diff"); | 
|---|
| 218 | args.append( "--name-only"); | 
|---|
| 219 | return textToLines(runGit(folder,args)); | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|
| 222 | QStringList GitManager::listConflicts(const QString &folder) | 
|---|
| 223 | { | 
|---|
| 224 | QStringList args; | 
|---|
| 225 | args.append( "diff"); | 
|---|
| 226 | args.append( "--name-only"); | 
|---|
| 227 | args.append( "--diff-filter=U"); | 
|---|
| 228 | return textToLines(runGit(folder,args)); | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | QStringList GitManager::listRemotes(const QString &folder) | 
|---|
| 232 | { | 
|---|
| 233 | QStringList args; | 
|---|
| 234 | args.append( "remote"); | 
|---|
| 235 | return textToLines(runGit(folder,args)); | 
|---|
| 236 | } | 
|---|
| 237 |  | 
|---|
| 238 | bool GitManager::removeRemote(const QString &folder, const QString &remoteName, QString& output) | 
|---|
| 239 | { | 
|---|
| 240 | QStringList args; | 
|---|
| 241 | args.append( "remote"); | 
|---|
| 242 | args.append( "remove"); | 
|---|
| 243 | args.append(remoteName); | 
|---|
| 244 |  | 
|---|
| 245 | output = runGit(folder,args); | 
|---|
| 246 | return isSuccess(output); | 
|---|
| 247 | } | 
|---|
| 248 |  | 
|---|
| 249 | bool GitManager::renameRemote(const QString &folder, const QString &oldName, const QString &newName, QString &output) | 
|---|
| 250 | { | 
|---|
| 251 | QStringList args; | 
|---|
| 252 | args.append( "remote"); | 
|---|
| 253 | args.append( "rename"); | 
|---|
| 254 | args.append(oldName); | 
|---|
| 255 | args.append(newName); | 
|---|
| 256 |  | 
|---|
| 257 | output = runGit(folder,args); | 
|---|
| 258 | return isSuccess(output); | 
|---|
| 259 | } | 
|---|
| 260 |  | 
|---|
| 261 | bool GitManager::addRemote(const QString &folder, const QString &name, const QString &url, QString &output) | 
|---|
| 262 | { | 
|---|
| 263 | QStringList args; | 
|---|
| 264 | args.append( "remote"); | 
|---|
| 265 | args.append( "add"); | 
|---|
| 266 | args.append(name); | 
|---|
| 267 | args.append(url); | 
|---|
| 268 |  | 
|---|
| 269 | output = runGit(folder,args); | 
|---|
| 270 | return isSuccess(output); | 
|---|
| 271 | } | 
|---|
| 272 |  | 
|---|
| 273 | bool GitManager::setRemoteURL(const QString &folder, const QString &name, const QString &newURL, QString &output) | 
|---|
| 274 | { | 
|---|
| 275 | QStringList args; | 
|---|
| 276 | args.append( "remote"); | 
|---|
| 277 | args.append( "set-url"); | 
|---|
| 278 | args.append(name); | 
|---|
| 279 | args.append(newURL); | 
|---|
| 280 |  | 
|---|
| 281 | output = runGit(folder,args); | 
|---|
| 282 | return isSuccess(output); | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | QString GitManager::getRemoteURL(const QString &folder, const QString &name) | 
|---|
| 286 | { | 
|---|
| 287 | QStringList args; | 
|---|
| 288 | args.append( "remote"); | 
|---|
| 289 | args.append( "get-url"); | 
|---|
| 290 | args.append(name); | 
|---|
| 291 | return runGit(folder,args).trimmed(); | 
|---|
| 292 | } | 
|---|
| 293 |  | 
|---|
| 294 | QString GitManager::getBranchRemote(const QString &folder, const QString &branch) | 
|---|
| 295 | { | 
|---|
| 296 | QStringList args; | 
|---|
| 297 | args.append( "config"); | 
|---|
| 298 | args.append( "--get"); | 
|---|
| 299 | args.append(QString( "branch.%1.remote").arg(branch)); | 
|---|
| 300 | return runGit(folder,args).trimmed(); | 
|---|
| 301 | } | 
|---|
| 302 |  | 
|---|
| 303 | QString GitManager::getBranchMerge(const QString &folder, const QString &branch) | 
|---|
| 304 | { | 
|---|
| 305 | QStringList args; | 
|---|
| 306 | args.append( "config"); | 
|---|
| 307 | args.append( "--get"); | 
|---|
| 308 | args.append(QString( "branch.%1.merge").arg(branch)); | 
|---|
| 309 | return runGit(folder,args).trimmed(); | 
|---|
| 310 | } | 
|---|
| 311 |  | 
|---|
| 312 | bool GitManager::setBranchUpstream( | 
|---|
| 313 | const QString &folder, | 
|---|
| 314 | const QString &branch, | 
|---|
| 315 | const QString &remoteName, | 
|---|
| 316 | QString& output) | 
|---|
| 317 | { | 
|---|
| 318 | QStringList args; | 
|---|
| 319 | args.append( "branch"); | 
|---|
| 320 | args.append(QString( "--set-upstream-to=%1/%2").arg(remoteName,branch)); | 
|---|
| 321 | args.append(branch); | 
|---|
| 322 | output = runGit(folder,args).trimmed(); | 
|---|
| 323 | return isSuccess(output); | 
|---|
| 324 | } | 
|---|
| 325 |  | 
|---|
| 326 | bool GitManager::fetch(const QString &folder, QString &output) | 
|---|
| 327 | { | 
|---|
| 328 | QStringList args; | 
|---|
| 329 | args.append( "fetch"); | 
|---|
| 330 | output = runGit(folder,args).trimmed(); | 
|---|
| 331 | return isSuccess(output); | 
|---|
| 332 | } | 
|---|
| 333 |  | 
|---|
| 334 | bool GitManager::pull(const QString &folder, QString &output) | 
|---|
| 335 | { | 
|---|
| 336 | QStringList args; | 
|---|
| 337 | args.append( "pull"); | 
|---|
| 338 | output = runGit(folder,args).trimmed(); | 
|---|
| 339 | return isSuccess(output); | 
|---|
| 340 | } | 
|---|
| 341 |  | 
|---|
| 342 | bool GitManager::push(const QString &folder, QString &output) | 
|---|
| 343 | { | 
|---|
| 344 | QStringList args; | 
|---|
| 345 | args.append( "push"); | 
|---|
| 346 | output = runGit(folder,args).trimmed(); | 
|---|
| 347 | return isSuccess(output); | 
|---|
| 348 | } | 
|---|
| 349 |  | 
|---|
| 350 | bool GitManager::push(const QString &folder, const QString &remoteName, const QString &branch, QString &output) | 
|---|
| 351 | { | 
|---|
| 352 | QStringList args; | 
|---|
| 353 | args.append( "push"); | 
|---|
| 354 | args.append( "--set-upstream"); | 
|---|
| 355 | args.append(remoteName); | 
|---|
| 356 | args.append(branch); | 
|---|
| 357 | output = runGit(folder,args).trimmed(); | 
|---|
| 358 | return isSuccess(output); | 
|---|
| 359 | } | 
|---|
| 360 |  | 
|---|
| 361 | bool GitManager::removeConfig(const QString &folder, const QString &name, QString &output) | 
|---|
| 362 | { | 
|---|
| 363 | QStringList args; | 
|---|
| 364 | args.append( "config"); | 
|---|
| 365 | args.append( "--unset-all"); | 
|---|
| 366 | args.append(name); | 
|---|
| 367 | output = runGit(folder,args); | 
|---|
| 368 | return isSuccess(output); | 
|---|
| 369 | } | 
|---|
| 370 |  | 
|---|
| 371 | bool GitManager::setConfig(const QString &folder, const QString &name, const QString &value, QString &output) | 
|---|
| 372 | { | 
|---|
| 373 | removeConfig(folder,name,output); | 
|---|
| 374 | QStringList args; | 
|---|
| 375 | args.append( "config"); | 
|---|
| 376 | args.append( "--add"); | 
|---|
| 377 | args.append(name); | 
|---|
| 378 | args.append(value); | 
|---|
| 379 | output = runGit(folder,args); | 
|---|
| 380 | return isSuccess(output); | 
|---|
| 381 | } | 
|---|
| 382 |  | 
|---|
| 383 | bool GitManager::setUserName(const QString &folder, const QString &userName, QString &output) | 
|---|
| 384 | { | 
|---|
| 385 | return setConfig(folder, "user.name",userName,output); | 
|---|
| 386 | } | 
|---|
| 387 |  | 
|---|
| 388 | bool GitManager::setUserEmail(const QString &folder, const QString &userEmail, QString &output) | 
|---|
| 389 | { | 
|---|
| 390 | return setConfig(folder, "user.email",userEmail,output); | 
|---|
| 391 | } | 
|---|
| 392 |  | 
|---|
| 393 | QString GitManager::getConfig(const QString& folder, const QString &name) | 
|---|
| 394 | { | 
|---|
| 395 | QStringList args; | 
|---|
| 396 | args.append( "config"); | 
|---|
| 397 | args.append( "--get"); | 
|---|
| 398 | args.append(name); | 
|---|
| 399 | return runGit(folder,args).trimmed(); | 
|---|
| 400 | } | 
|---|
| 401 |  | 
|---|
| 402 | QString GitManager::getUserName(const QString& folder) | 
|---|
| 403 | { | 
|---|
| 404 | return getConfig(folder, "user.name"); | 
|---|
| 405 | } | 
|---|
| 406 |  | 
|---|
| 407 | QString GitManager::getUserEmail(const QString& folder) | 
|---|
| 408 | { | 
|---|
| 409 | return getConfig(folder, "user.email"); | 
|---|
| 410 | } | 
|---|
| 411 |  | 
|---|
| 412 | QStringList GitManager::listBranches(const QString &folder, int ¤t) | 
|---|
| 413 | { | 
|---|
| 414 | QStringList args; | 
|---|
| 415 | args.append( "branch"); | 
|---|
| 416 | args.append( "-a"); | 
|---|
| 417 | args.append( "-l"); | 
|---|
| 418 | QStringList temp = textToLines(runGit(folder,args)); | 
|---|
| 419 | current = -1; | 
|---|
| 420 | for (int i=0;i<temp.length();i++) { | 
|---|
| 421 | QString s = temp[i]; | 
|---|
| 422 | if (s.startsWith('*')) { | 
|---|
| 423 | current = i; | 
|---|
| 424 | temp[i] = s.mid(1).trimmed(); | 
|---|
| 425 | } else if (s.startsWith('+')) { | 
|---|
| 426 | temp[i] = s.mid(1).trimmed(); | 
|---|
| 427 | } else { | 
|---|
| 428 | temp[i] = s.trimmed(); | 
|---|
| 429 | } | 
|---|
| 430 | } | 
|---|
| 431 | return temp; | 
|---|
| 432 | } | 
|---|
| 433 |  | 
|---|
| 434 | bool GitManager::switchToBranch(const QString &folder, const QString &branch, | 
|---|
| 435 | bool create, bool force, bool merge, bool track, | 
|---|
| 436 | bool noTrack, bool forceCreation, QString& output) | 
|---|
| 437 | { | 
|---|
| 438 | QStringList args; | 
|---|
| 439 | args.append( "switch"); | 
|---|
| 440 | if (forceCreation) | 
|---|
| 441 | args.append( "-C"); | 
|---|
| 442 | else if (create) | 
|---|
| 443 | args.append( "-c"); | 
|---|
| 444 | if (merge) | 
|---|
| 445 | args.append( "-m"); | 
|---|
| 446 | if (force) | 
|---|
| 447 | args.append( "-f"); | 
|---|
| 448 | if (track) | 
|---|
| 449 | args.append( "--track"); | 
|---|
| 450 | else if (noTrack) | 
|---|
| 451 | args.append( "--no-track"); | 
|---|
| 452 | args.append(branch); | 
|---|
| 453 | output = runGit(folder,args); | 
|---|
| 454 | return isSuccess(output); | 
|---|
| 455 | } | 
|---|
| 456 |  | 
|---|
| 457 | bool GitManager::merge(const QString &folder, const QString &commit, bool squash, | 
|---|
| 458 | bool fastForwardOnly, bool noFastForward, bool noCommit, | 
|---|
| 459 | QString& output, | 
|---|
| 460 | const QString& commitMessage) | 
|---|
| 461 | { | 
|---|
| 462 | QStringList args; | 
|---|
| 463 | args.append( "merge"); | 
|---|
| 464 | if (squash) | 
|---|
| 465 | args.append( "--squash"); | 
|---|
| 466 | if (fastForwardOnly) | 
|---|
| 467 | args.append( "--ff-only"); | 
|---|
| 468 | else if (noFastForward) | 
|---|
| 469 | args.append( "--no-ff"); | 
|---|
| 470 | if (noCommit) | 
|---|
| 471 | args.append( "--no-commit"); | 
|---|
| 472 | if (!commitMessage.isEmpty() | 
|---|
| 473 | && commitMessage != QObject::tr( "<Auto Generated by Git>")){ | 
|---|
| 474 | args.append( "-m"); | 
|---|
| 475 | args.append(commitMessage); | 
|---|
| 476 | } | 
|---|
| 477 | args.append(commit); | 
|---|
| 478 | output = runGit(folder,args); | 
|---|
| 479 | return isSuccess(output); | 
|---|
| 480 | } | 
|---|
| 481 |  | 
|---|
| 482 | bool GitManager::continueMerge(const QString &folder) | 
|---|
| 483 | { | 
|---|
| 484 | QStringList args; | 
|---|
| 485 | args.append( "merge"); | 
|---|
| 486 | args.append( "--continue"); | 
|---|
| 487 | QString output = runGit(folder,args); | 
|---|
| 488 | return isSuccess(output); | 
|---|
| 489 |  | 
|---|
| 490 | } | 
|---|
| 491 |  | 
|---|
| 492 | void GitManager::abortMerge(const QString &folder) | 
|---|
| 493 | { | 
|---|
| 494 | QStringList args; | 
|---|
| 495 | args.append( "merge"); | 
|---|
| 496 | args.append( "--abort"); | 
|---|
| 497 | runGit(folder,args); | 
|---|
| 498 | } | 
|---|
| 499 |  | 
|---|
| 500 | bool GitManager::isSuccess(const QString &output) | 
|---|
| 501 | { | 
|---|
| 502 | QStringList lst = textToLines(output); | 
|---|
| 503 | if (!lst.isEmpty()) { | 
|---|
| 504 | foreach (const QString& s, lst) { | 
|---|
| 505 | QString last= s.trimmed(); | 
|---|
| 506 | if (last.startsWith( "error:") || last.startsWith( "fatal:")) | 
|---|
| 507 | return false; | 
|---|
| 508 | } | 
|---|
| 509 | return true; | 
|---|
| 510 | } | 
|---|
| 511 | return true; | 
|---|
| 512 | } | 
|---|
| 513 |  | 
|---|
| 514 | bool GitManager::clone(const QString &folder, const QString &url, QString& output) | 
|---|
| 515 | { | 
|---|
| 516 | QStringList args; | 
|---|
| 517 | args.append( "clone"); | 
|---|
| 518 | args.append(url); | 
|---|
| 519 | output = runGit(folder,args); | 
|---|
| 520 | return isSuccess(output); | 
|---|
| 521 | } | 
|---|
| 522 |  | 
|---|
| 523 | bool GitManager::commit(const QString &folder, const QString &message, bool autoStage, QString& output) | 
|---|
| 524 | { | 
|---|
| 525 | QStringList args; | 
|---|
| 526 | args.append( "commit"); | 
|---|
| 527 | if (autoStage) | 
|---|
| 528 | args.append( "-a"); | 
|---|
| 529 | args.append( "-m"); | 
|---|
| 530 | args.append(message); | 
|---|
| 531 | output = runGit(folder,args); | 
|---|
| 532 | return isSuccess(output); | 
|---|
| 533 | } | 
|---|
| 534 |  | 
|---|
| 535 | bool GitManager::revert(const QString &folder, QString& output) | 
|---|
| 536 | { | 
|---|
| 537 | QStringList args; | 
|---|
| 538 | args.append( "revert"); | 
|---|
| 539 | output = runGit(folder,args); | 
|---|
| 540 | return isSuccess(output); | 
|---|
| 541 | } | 
|---|
| 542 |  | 
|---|
| 543 | bool GitManager::reset(const QString &folder, const QString &commit, | 
|---|
| 544 | GitResetStrategy strategy, | 
|---|
| 545 | QString& output) | 
|---|
| 546 | { | 
|---|
| 547 | //todo reset type | 
|---|
| 548 | QStringList args; | 
|---|
| 549 | args.append( "reset"); | 
|---|
| 550 | switch(strategy) { | 
|---|
| 551 | case GitResetStrategy::Soft: | 
|---|
| 552 | args.append( "--soft"); | 
|---|
| 553 | break; | 
|---|
| 554 | case GitResetStrategy::Hard: | 
|---|
| 555 | args.append( "--hard"); | 
|---|
| 556 | break; | 
|---|
| 557 | case GitResetStrategy::Mixed: | 
|---|
| 558 | args.append( "--mixed"); | 
|---|
| 559 | break; | 
|---|
| 560 | case GitResetStrategy::Merge: | 
|---|
| 561 | args.append( "--merge"); | 
|---|
| 562 | break; | 
|---|
| 563 | case GitResetStrategy::Keep: | 
|---|
| 564 | args.append( "--keep"); | 
|---|
| 565 | break; | 
|---|
| 566 | } | 
|---|
| 567 | args.append(commit); | 
|---|
| 568 | output = runGit(folder,args); | 
|---|
| 569 | return isSuccess(output); | 
|---|
| 570 | } | 
|---|
| 571 |  | 
|---|
| 572 | bool GitManager::isValid() | 
|---|
| 573 | { | 
|---|
| 574 | return pSettings->vcs().gitOk(); | 
|---|
| 575 | } | 
|---|
| 576 |  | 
|---|
| 577 | QString GitManager::runGit(const QString& workingFolder, const QStringList &args) | 
|---|
| 578 | { | 
|---|
| 579 | if (!isValid()) | 
|---|
| 580 | return ""; | 
|---|
| 581 | QFileInfo fileInfo(pSettings->vcs().gitPath()); | 
|---|
| 582 | if (!fileInfo.exists()) | 
|---|
| 583 | return "fatal: git doesn't exist"; | 
|---|
| 584 | emit gitCmdRunning(QString( "Running in \"%1\": \n \"%2\" \"%3\"") | 
|---|
| 585 | .arg(workingFolder, | 
|---|
| 586 | pSettings->vcs().gitPath(), | 
|---|
| 587 | args.join( "\" \""))); | 
|---|
| 588 | //    qDebug()<<"---------"; | 
|---|
| 589 | //    qDebug()<<args; | 
|---|
| 590 | QProcessEnvironment env; | 
|---|
| 591 | #ifdef Q_OS_WIN | 
|---|
| 592 | env.insert( "PATH",pSettings->dirs().appDir()); | 
|---|
| 593 | env.insert( "GIT_ASKPASS",includeTrailingPathDelimiter(pSettings->dirs().appDir())+ "redpanda-win-git-askpass.exe"); | 
|---|
| 594 | #elif defined(Q_OS_LINUX) | 
|---|
| 595 | env.insert(QProcessEnvironment::systemEnvironment()); | 
|---|
| 596 | env.insert( "LANG", "en"); | 
|---|
| 597 | env.insert( "LANGUAGE", "en"); | 
|---|
| 598 | env.insert( "GIT_ASKPASS",includeTrailingPathDelimiter(pSettings->dirs().appLibexecDir())+ "redpanda-git-askpass"); | 
|---|
| 599 | #endif | 
|---|
| 600 | QString output = runAndGetOutput( | 
|---|
| 601 | fileInfo.absoluteFilePath(), | 
|---|
| 602 | workingFolder, | 
|---|
| 603 | args, | 
|---|
| 604 | "", | 
|---|
| 605 | false, | 
|---|
| 606 | env); | 
|---|
| 607 | output = escapeUTF8String(output.toUtf8()); | 
|---|
| 608 | //    qDebug()<<output; | 
|---|
| 609 | emit gitCmdFinished(output); | 
|---|
| 610 | //    if (output.startsWith("fatal:")) | 
|---|
| 611 | //        throw GitError(output); | 
|---|
| 612 | return output; | 
|---|
| 613 | } | 
|---|
| 614 |  | 
|---|
| 615 | QString GitManager::escapeUTF8String(const QByteArray &rawString) | 
|---|
| 616 | { | 
|---|
| 617 | QByteArray stringValue; | 
|---|
| 618 | int p = 0; | 
|---|
| 619 | while (p<rawString.length()) { | 
|---|
| 620 | char ch = rawString[p]; | 
|---|
| 621 | if (ch =='\\' && p+1 < rawString.length()) { | 
|---|
| 622 | p++; | 
|---|
| 623 | ch = rawString[p]; | 
|---|
| 624 | switch (ch) { | 
|---|
| 625 | case '\'': | 
|---|
| 626 | stringValue+=0x27; | 
|---|
| 627 | p++; | 
|---|
| 628 | break; | 
|---|
| 629 | case '"': | 
|---|
| 630 | stringValue+=0x22; | 
|---|
| 631 | p++; | 
|---|
| 632 | break; | 
|---|
| 633 | case '?': | 
|---|
| 634 | stringValue+=0x3f; | 
|---|
| 635 | p++; | 
|---|
| 636 | break; | 
|---|
| 637 | case '\\': | 
|---|
| 638 | stringValue+=0x5c; | 
|---|
| 639 | p++; | 
|---|
| 640 | break; | 
|---|
| 641 | case 'a': | 
|---|
| 642 | stringValue+=0x07; | 
|---|
| 643 | p++; | 
|---|
| 644 | break; | 
|---|
| 645 | case 'b': | 
|---|
| 646 | stringValue+=0x08; | 
|---|
| 647 | p++; | 
|---|
| 648 | break; | 
|---|
| 649 | case 'f': | 
|---|
| 650 | stringValue+=0x0c; | 
|---|
| 651 | p++; | 
|---|
| 652 | break; | 
|---|
| 653 | case 'n': | 
|---|
| 654 | stringValue+=0x0a; | 
|---|
| 655 | p++; | 
|---|
| 656 | break; | 
|---|
| 657 | case 'r': | 
|---|
| 658 | stringValue+=0x0d; | 
|---|
| 659 | p++; | 
|---|
| 660 | break; | 
|---|
| 661 | case 't': | 
|---|
| 662 | stringValue+=0x09; | 
|---|
| 663 | p++; | 
|---|
| 664 | break; | 
|---|
| 665 | case 'v': | 
|---|
| 666 | stringValue+=0x0b; | 
|---|
| 667 | p++; | 
|---|
| 668 | break; | 
|---|
| 669 | case '0': | 
|---|
| 670 | case '1': | 
|---|
| 671 | case '2': | 
|---|
| 672 | case '3': | 
|---|
| 673 | case '4': | 
|---|
| 674 | case '5': | 
|---|
| 675 | case '6': | 
|---|
| 676 | case '7': | 
|---|
| 677 | { | 
|---|
| 678 | int i=0; | 
|---|
| 679 | for (i=0;i<3;i++) { | 
|---|
| 680 | if (p+i>=rawString.length() || | 
|---|
| 681 | rawString[p+i]<'0' || rawString[p+i]>'7') | 
|---|
| 682 | break; | 
|---|
| 683 | } | 
|---|
| 684 | bool ok; | 
|---|
| 685 | unsigned char ch = rawString.mid(p,i).toInt(&ok,8); | 
|---|
| 686 | stringValue+=ch; | 
|---|
| 687 | p+=i; | 
|---|
| 688 | break; | 
|---|
| 689 | } | 
|---|
| 690 | } | 
|---|
| 691 | } else { | 
|---|
| 692 | if (ch!='\"') | 
|---|
| 693 | stringValue+=ch; | 
|---|
| 694 | p++; | 
|---|
| 695 | } | 
|---|
| 696 | } | 
|---|
| 697 | return QString::fromUtf8(stringValue); | 
|---|
| 698 | } | 
|---|
| 699 |  | 
|---|
| 700 | GitError::GitError(const QString &reason):BaseError(reason) | 
|---|
| 701 | { | 
|---|
| 702 |  | 
|---|
| 703 | } | 
|---|
| 704 |  | 
|---|