+string const CVS::getTarget(OperationMode opmode) const
+{
+ switch(opmode) {
+ case Directory:
+ // in client server mode CVS does not like full path operand for directory operation
+ // since LyX switches to the repo dir "." is good enough as target
+ return ".";
+ case File:
+ return quoteName(onlyFileName(owner_->absFileName()));
+ }
+ return string();
+}
+
+
+docstring CVS::toString(CvsStatus status) const
+{
+ switch (status) {
+ case UpToDate:
+ return _("Up-to-date");
+ case LocallyModified:
+ return _("Locally Modified");
+ case LocallyAdded:
+ return _("Locally Added");
+ case NeedsMerge:
+ return _("Needs Merge");
+ case NeedsCheckout:
+ return _("Needs Checkout");
+ case NoCvsFile:
+ return _("No CVS file");
+ case StatusError:
+ return _("Cannot retrieve CVS status");
+ }
+ return 0;
+}
+
+
+int CVS::doVCCommandWithOutput(string const & cmd, FileName const & path,
+ FileName const & output, bool reportError)
+{
+ string redirection = output.empty() ? "" : " > " + quoteName(output.toFilesystemEncoding());
+ return doVCCommand(cmd + redirection, path, reportError);
+}
+
+
+int CVS::doVCCommandCallWithOutput(std::string const & cmd,
+ support::FileName const & path,
+ support::FileName const & output)
+{
+ string redirection = output.empty() ? "" : " > " + quoteName(output.toFilesystemEncoding());
+ return doVCCommandCall(cmd + redirection, path);
+}
+
+
+CVS::CvsStatus CVS::getStatus()
+{
+ FileName tmpf = FileName::tempName("lyxvcout");
+ if (tmpf.empty()) {
+ LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
+ return StatusError;
+ }
+
+ if (doVCCommandCallWithOutput("cvs status " + getTarget(File),
+ FileName(owner_->filePath()), tmpf)) {
+ tmpf.removeFile();
+ return StatusError;
+ }
+
+ ifstream ifs(tmpf.toFilesystemEncoding().c_str());
+ CvsStatus status = NoCvsFile;
+
+ while (ifs) {
+ string line;
+ getline(ifs, line);
+ LYXERR(Debug::LYXVC, line << "\n");
+ if (prefixIs(line, "File:")) {
+ if (contains(line, "Up-to-date"))
+ status = UpToDate;
+ else if (contains(line, "Locally Modified"))
+ status = LocallyModified;
+ else if (contains(line, "Locally Added"))
+ status = LocallyAdded;
+ else if (contains(line, "Needs Merge"))
+ status = NeedsMerge;
+ else if (contains(line, "Needs Checkout"))
+ status = NeedsCheckout;
+ }
+ }
+ tmpf.removeFile();
+ return status;
+}
+
+void CVS::getRevisionInfo()
+{
+ if (have_rev_info_)
+ return;
+ have_rev_info_ = true;
+ FileName tmpf = FileName::tempName("lyxvcout");
+ if (tmpf.empty()) {
+ LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
+ return;
+ }
+
+ int rc = doVCCommandCallWithOutput("cvs log -r" + version_
+ + " " + getTarget(File),
+ FileName(owner_->filePath()), tmpf);
+ if (rc) {
+ tmpf.removeFile();
+ LYXERR(Debug::LYXVC, "cvs log failed with exit code " << rc);
+ return;
+ }
+
+ ifstream ifs(tmpf.toFilesystemEncoding().c_str());
+ static regex const reg("date: (.*) (.*) (.*); author: (.*); state: (.*);(.*)");
+
+ while (ifs) {
+ string line;
+ getline(ifs, line);
+ LYXERR(Debug::LYXVC, line << "\n");
+ if (prefixIs(line, "date:")) {
+ smatch sm;
+ regex_match(line, sm, reg);
+ //sm[0]; // whole matched string
+ rev_date_cache_ = sm[1];
+ rev_time_cache_ = sm[2];
+ //sm[3]; // GMT offset
+ rev_author_cache_ = sm[4];
+ break;
+ }
+ }
+ tmpf.removeFile();
+ if (rev_author_cache_.empty())
+ LYXERR(Debug::LYXVC,
+ "Could not retrieve revision info for " << version_ <<
+ " of " << getTarget(File));
+}
+
+