00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 #include "svn.hpp"
00016 #include "gui/principal.h"
00017 
00018 Svn::Svn(Principal* cl) : 
00019         needs_refresh_(false), out_win_(cl->messagesBrowser), show_enable_(true), parent_(cl)
00020 {
00021         caller = cl;
00022         proc = new QProcess(this);
00023         svn_ = "svn";
00024         is_ready_for_last_command_ = false;
00025         connect(proc, SIGNAL(readyReadStdout()), this, SLOT(readFromStdout()) );
00026         connect(proc, SIGNAL(readyReadStderr()), this, SLOT(readFromStderr()) );
00027         connect(proc, SIGNAL(processExited()), this, SLOT(procFinished()) );
00028 };
00029 
00030 void Svn::common(QString command)
00031 {
00032         proc->clearArguments();
00033         proc->addArgument(svn_);
00034         proc->addArgument(command);
00035 }
00036 
00037 int Svn::diff(const QString& file_dir_name_1, const QString& file_dir_name_2, 
00038                         const QString& rev, bool use_external_cmd, bool non_recursive, bool notice_ancestry, 
00039                         const QString& extensions,  QStringList& out_txt) 
00040 {
00041         common("diff");
00042 
00043         if (rev != "") {
00044                 proc->addArgument("-r");
00045                 proc->addArgument(rev);
00046         }
00047 
00048         if (!file_dir_name_1.isEmpty()) {
00049                 if (!file_dir_name_2.isEmpty()) {
00050                         proc->addArgument("--old");
00051                         proc->addArgument(QDir::convertSeparators(file_dir_name_1));
00052                         proc->addArgument("--new");
00053                         proc->addArgument(QDir::convertSeparators(file_dir_name_2));
00054                 } else {
00055                         
00056                         proc->addArgument(QDir::convertSeparators(file_dir_name_1));
00057                 }
00058         }
00059 
00060         if (non_recursive) 
00061                 proc->addArgument("--non-recursive");
00062 
00063         if (notice_ancestry) 
00064                 proc->addArgument("--notice-ancestry");
00065 
00066         if (!extensions.isEmpty()) {
00067                 proc->addArgument("--extensions");
00068                 proc->addArgument(extensions);      
00069         }
00070 
00071         if (use_external_cmd) {
00072                 proc->addArgument("--diff-cmd");
00073                 return execCommand(false);
00074         }
00075         else    
00076         return execCommand(SC_APPEND_USER_PASS, &out_txt);
00077 }
00078 
00079 int Svn::update(const QString& revision)
00080 {
00081         common("update");
00082 
00083         if (revision != "") {
00084                 proc->addArgument("-r");
00085                 proc->addArgument(revision);
00086         }
00087         proc->addArgument(caller->wd);
00088         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00089 }
00090 
00091 int Svn::log(const QString& filename, bool is_verbouse, bool stop_on_copy, QStringList& out_txt)
00092 {
00093         common("log");
00094         if (is_verbouse)
00095                 proc->addArgument("--verbose");
00096         if (stop_on_copy)
00097                 proc->addArgument("--stop-on-copy");
00098                 proc->addArgument(filename);
00099                 return execCommand(SC_APPEND_USER_PASS, &out_txt);
00100 }
00101 
00102 int Svn::status() {
00103         common("status");
00104         proc->addArgument(caller->wd);
00105         proc->addArgument("--verbose");
00106         return execCommand(SC_APPEND_USER_PASS | SC_WAIT);
00107 }
00108 
00109 int Svn::info(const QString& filename, QStringList& out_txt, bool hideOutput) {
00110         common("info");
00111         proc->addArgument(filename);
00112         if (hideOutput)
00113                 return execCommand(SC_HIDE, &out_txt);
00114         else
00115                 return execCommand(0, &out_txt);
00116 }
00117 
00118 int Svn::commit(const QString& wd, QString msg) {
00119         common("commit");
00120 
00121         if (msg == "")
00122                 msg = "nomsg";
00123         proc->addArgument("-m");
00124         proc->addArgument(msg);
00125         if (wd != "")
00126                 proc->addArgument(wd);
00127         return execCommand(SC_REFRESH | SC_WAIT | SC_APPEND_USER_PASS);
00128 }
00129 
00130 int Svn::cleanup(QString& wd) {
00131         common("cleanup");
00132         if (wd != "")
00133                 proc->addArgument(wd);
00134         return execCommand(SC_WAIT);
00135 }
00136 
00137 int Svn::revert(const QString& filename, bool recursive) {
00138         common("revert");
00139         if (recursive) 
00140                 proc->addArgument("--recursive");
00141         if (filename != "") 
00142                 proc->addArgument(filename);
00143         return execCommand(SC_REFRESH | SC_WAIT);
00144 }
00145 
00146 int Svn::resolve(const QString& filename) {
00147         common("resolved");
00148         if (filename != "")
00149                 proc->addArgument(filename);
00150         return execCommand(SC_REFRESH | SC_WAIT);
00151 }
00152 
00153 int Svn::add(const QString& filename, bool recursive) {
00154         common("add");
00155         if (!recursive)
00156                 proc->addArgument("-N");
00157         proc->addArgument(filename);
00158         return execCommand(SC_REFRESH | SC_WAIT);
00159 }
00160 
00161 int Svn::del(const QString filename) {
00162         common("delete");
00163         proc->addArgument(filename);
00164         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00165 }
00166 
00167 int Svn::copy(QString& src, const QString &dst, const QString& msg, const QString& rev) {
00168         common("copy");
00169         proc->addArgument(src);
00170         proc->addArgument(dst);
00171         proc->addArgument("-m");
00172         if (msg == "")
00173                 proc->addArgument("\"copied\"");
00174         else
00175                 proc->addArgument(msg);
00176         if (rev != "") {
00177                 proc->addArgument("-r");
00178                 proc->addArgument(rev);
00179         }
00180         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00181 }
00182 
00183 int Svn::move(const QString& src, const QString &dst, const QString& msg, const QString& rev) {
00184         common("move");
00185         proc->addArgument(src);
00186         proc->addArgument(dst);
00187         proc->addArgument("-m");
00188         if (msg == "")
00189                 proc->addArgument("\"moved\"");
00190         else
00191                 proc->addArgument(msg);
00192         if (rev != "") {
00193                 proc->addArgument("-r");
00194                 proc->addArgument(rev);
00195         }
00196         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00197 }
00198 
00199 int Svn::switch_cmd(const QString& url, const QString &rev, bool non_recursive) {
00200         common("switch");
00201         if (rev != "") {
00202                 proc->addArgument("-r");
00203                 proc->addArgument(rev);
00204         }
00205         if (non_recursive)
00206                 proc->addArgument("--non-recursive");
00207         proc->addArgument(url);
00208         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00209 }
00210 
00211 int Svn::merge(const QString& file_dir_name, const QString& first, const QString &second,
00212                                 const QString& wcpath, bool use_rev, bool non_recursive, bool dryrun) {
00213         common("merge");
00214         if (non_recursive)
00215                 proc->addArgument("--non-recursive");
00216         if (dryrun)
00217                 proc->addArgument("--dry-run");
00218         if (use_rev) {
00219                 proc->addArgument("-r");
00220                 proc->addArgument(first+":"+second);
00221                 proc->addArgument(file_dir_name);
00222         }
00223         else {
00224                 proc->addArgument(first);
00225                 proc->addArgument(second);
00226         }
00227         if (!wcpath.isEmpty()) 
00228                 proc->addArgument(wcpath);
00229         return execCommand(SC_REFRESH | SC_WAIT);
00230 }
00231 
00232 int Svn::cat(const QString& filename, const QString& rev, QStringList& out_txt) {
00233         common("cat");
00234         proc->addArgument(filename);
00235         if (rev != "") {
00236                 proc->addArgument("-r");
00237                 proc->addArgument(rev);
00238         }
00239         return execCommand(SC_APPEND_USER_PASS, &out_txt);
00240 }
00241 
00242 int Svn::blame(const QString& filename, const QString& rev, QStringList& out_txt) {
00243         common("blame");
00244         proc->addArgument(filename);
00245         if (rev != "") {
00246                 proc->addArgument("-r");
00247                 proc->addArgument(rev);
00248         }
00249         return execCommand(SC_APPEND_USER_PASS, &out_txt);
00250 }
00251 
00252 int Svn::checkout(const QString &rev, bool non_recursive) {
00253         common("checkout");
00254         proc->addArgument(caller->adress + caller->wd);
00255         proc->addArgument(caller->wd);
00256 
00257         if (rev != "") {
00258                 proc->addArgument("-r");
00259                 proc->addArgument(rev);
00260         }
00261         if (non_recursive)
00262                 proc->addArgument("--non-recursive");
00263         proc->addArgument("--non-interactive");
00264 
00265         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00266 }
00267 
00268 int Svn::export_cmd(const QString& url, const QString& local_path, const QString &rev) {
00269         common("export");
00270         proc->addArgument(url);
00271         proc->addArgument(local_path);
00272         if (rev != "") {
00273                 proc->addArgument("-r");
00274                 proc->addArgument(rev);
00275         }
00276         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00277 }
00278 
00279 int Svn::import(const QString& url, const QString& local_path, QString msg,  bool non_recursive) {
00280         common("import");
00281         proc->addArgument(local_path);
00282         proc->addArgument(url);
00283         if (msg == "")
00284                 msg = "nomsg";
00285         proc->addArgument("-m"); 
00286         proc->addArgument(msg);
00287         if (non_recursive)
00288                 proc->addArgument("--non-recursive");
00289         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00290 }
00291 
00292 int Svn::mkdir(const QString& dir) {
00293         common("mkdir");
00294         proc->addArgument(dir);
00295         return execCommand(SC_REFRESH | SC_APPEND_USER_PASS | SC_WAIT);
00296 }
00297 
00298 int Svn::proplist(const QString& filename, const QString& rev, QStringList& out_txt) {
00299         common("proplist");
00300         proc->addArgument(filename);
00301         proc->addArgument("--verbose");
00302         if (!rev.isEmpty()) {
00303                 proc->addArgument("-r");
00304                 proc->addArgument(rev);
00305         }
00306         return execCommand(SC_WAIT | SC_APPEND_USER_PASS, &out_txt);
00307 }
00308 
00309 int Svn::propset(const QString& filename, const QString& rev, const QString& key, const QString &value) {
00310         common("propset");
00311         proc->addArgument(key);
00312         proc->addArgument(value);
00313         proc->addArgument(filename);
00314         if (rev != "") {
00315                 proc->addArgument("-r");
00316                 proc->addArgument(rev);
00317         }
00318         return execCommand(SC_WAIT | SC_APPEND_USER_PASS);
00319 }
00320 
00321 int Svn::propdel(const QString& filename, const QString& rev, const QString& key) {
00322         common("propdel");
00323         proc->addArgument(key);
00324         proc->addArgument(filename);
00325         if (rev != "") {
00326                 proc->addArgument("-r");
00327                 proc->addArgument(rev);
00328         }
00329         return execCommand(SC_WAIT | SC_APPEND_USER_PASS);
00330 }
00331 
00332 int Svn::list(const QString& url, const QString& rev, QStringList& out_txt, bool is_hide,
00333                         bool recursive, bool dont_change_cursor) {
00334         common("list");
00335         proc->addArgument(url);
00336         if (recursive)
00337                 proc->addArgument("--recursive");
00338         proc->addArgument("--verbose");
00339         if (rev != "") {
00340                 proc->addArgument("-r");
00341                 proc->addArgument(rev);
00342         }
00343         return execCommand(SC_WAIT | SC_APPEND_USER_PASS | (dont_change_cursor ? SC_DISABLE_CURSOR_CHANGE : 0) | (is_hide ? SC_HIDE : 0), &out_txt);
00344 }
00345 
00346 void Svn::setSvn(QString svn){
00347         svn_ = svn;
00348 }
00349 
00350 int Svn::getLastRev() {
00351         QStringList infoOutput;
00352         if (info(caller->adress + caller->wd + "/prop.graphml", infoOutput,true))
00353                 info(caller->wd + "/prop.graphml", infoOutput,true);
00354         infoOutput = infoOutput.grep("Revision");
00355         QString stemp = infoOutput.first();
00356         stemp = stemp.right( stemp.length() - 10);
00357         return stemp.toInt();
00358 }
00359 
00360 
00361 
00362 void Svn::readFromStdout() {
00363         while (proc->canReadLineStdout()) {
00364                 QString src_msg = proc->readLineStdout();
00365                 QString str = QTextCodec::codecForLocale()->toUnicode(src_msg);
00366                 if(!str.isNull()){
00367                         if (show_enable_)
00368                                 out_win_->append(QString("<font color=black>") + str + QString("</font>") );
00369                         out_text_.push_back(str);
00370                 }
00371         }
00372 }
00373 
00374 void Svn::readFromStderr() {     
00375         while (proc->canReadLineStderr()) {
00376                 QString str = QTextCodec::codecForLocale()->toUnicode(proc->readLineStderr());
00377                 out_win_->append(QString("<font color=red>") + str + QString("</font>") );
00378                 if (!disable_cursor_change_) 
00379                         QApplication::restoreOverrideCursor();
00380         }
00381 }
00382 
00383 void Svn::procFinished() {
00384         parent_->blockSignals(false);   
00385         if (!disable_cursor_change_) 
00386                 QApplication::restoreOverrideCursor();
00387         if (!is_hide_all_) {
00388                 int ret_code = proc->exitStatus();
00389                 char ret_code_buff[64];
00390                 if (ret_code == 0)
00391                         sprintf(ret_code_buff, "<font color=darkgreen>successfully (%d)</font>", ret_code);
00392                 else
00393                         sprintf(ret_code_buff, "<font color=darkred>error (%d)</font>", ret_code);
00394                 out_win_->append(ret_code_buff);
00395         }
00396         if (is_refreshable_command_)
00397                 needs_refresh_ = true;
00398         is_ready_for_last_command_ = true;        
00399 }
00400 
00401 QString Svn::getLastCommand() {
00402         if (is_ready_for_last_command_) {
00403                 QStringList args = proc->arguments();
00404                 if (args.empty())
00405                         return "";
00406                 else {
00407                         is_ready_for_last_command_ = false;
00408                         return args[1];
00409                 }
00410         }
00411         else
00412                 return "";
00413 }
00414 
00415 
00416 int Svn::execCommand(unsigned int flags, QStringList* out_list) {
00417         disable_cursor_change_ = (flags & SC_DISABLE_CURSOR_CHANGE);
00418 
00419         if (!disable_cursor_change_) 
00420                 QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
00421         is_refreshable_command_ = (flags & SC_REFRESH);
00422 
00423         if (flags & SC_APPEND_USER_PASS) {
00424                 proc->addArgument("--username");
00425                 proc->addArgument(caller->login());
00426                 proc->addArgument("--password");
00427                 proc->addArgument(caller->password());
00428                 proc->addArgument("--non-interactive");
00429         }
00430         is_hide_all_ = (flags & SC_HIDE);
00431 
00432         if (!is_hide_all_ ) {
00433                 QString svn_cmd = showCommand();
00434         }
00435 
00436         show_enable_ = (!out_list && !is_hide_all_);
00437         out_text_.clear();
00438         qApp->processEvents();
00439 
00440         proc->setWorkingDirectory(qApp->applicationDirPath());
00441 
00442         if (!proc->start()) {
00443                 out_text_.append(tr("can't fork the process"));
00444 
00445                 if (!disable_cursor_change_) 
00446                         QApplication::restoreOverrideCursor();
00447                 return 1;
00448         }
00449 
00450         parent_->blockSignals(true);
00451         if (out_list || (flags & SC_WAIT) ) {
00452 
00453                 while (proc->isRunning()) {
00454                         qApp->processEvents(QEventLoop::ExcludeUserInput);
00455                 }
00456 
00457                 if (!disable_cursor_change_) 
00458                         QApplication::restoreOverrideCursor();
00459         }
00460 
00461         if (out_list)
00462                 *out_list = out_text_;
00463 
00464         show_enable_ = true;
00465         int ret_code = proc->exitStatus();
00466         return ret_code;
00467 }
00468 
00469 QString Svn::showCommand() {
00470         QStringList args = proc->arguments();
00471         QStringList::Iterator it = args.begin();
00472         QString out_str = "<font color=navy>";
00473         QString curr_str, prev_arg;
00474         int arg_num =0;
00475         while ( it != args.end() ) {
00476                 if (arg_num && prev_arg == QString("--password") )
00477                         curr_str = "******";
00478                 else
00479                         curr_str = (*it);
00480                 if (arg_num++ == 1)
00481                         out_str = out_str + curr_str + "</font> ";
00482                 else
00483                         out_str = out_str + curr_str + " ";
00484                 ++it;
00485                 prev_arg = curr_str;
00486         }
00487         out_win_->append(out_str);
00488         return out_str;
00489 }