The branch, master, has been updated. - Log -----------------------------------------------------------------
commit a3e6c7830c979f5c891179061507e6a50a210026 Author: Georg Baum <[email protected]> Date: Tue Feb 5 21:40:19 2013 +0100 Fix copy-paste error diff --git a/src/LyXVC.cpp b/src/LyXVC.cpp index 4f6492e..a697d9d 100644 --- a/src/LyXVC.cpp +++ b/src/LyXVC.cpp @@ -143,7 +143,7 @@ bool LyXVC::registrer() if (svn_entries.isReadableFile()) { LYXERR(Debug::LYXVC, "LyXVC: registering " << to_utf8(filename.displayName()) << " with SVN"); - vcs.reset(new SVN(cvs_entries, owner_)); + vcs.reset(new SVN(svn_entries, owner_)); } else if (cvs_entries.isReadableFile()) { LYXERR(Debug::LYXVC, "LyXVC: registering " commit 0526eb9d47008ba8d63452a32e8cdc73a272b7f1 Author: Georg Baum <[email protected]> Date: Tue Feb 5 21:31:58 2013 +0100 Implement VCS copy and rename The advantage of having this in LyX is the intelligent file name handling of included files. Implementation as discussed on the list, but ensure also that an attempt to use locked files fails. diff --git a/lib/doc/Additional.lyx b/lib/doc/Additional.lyx index f9cf459..3bfa4e6 100644 --- a/lib/doc/Additional.lyx +++ b/lib/doc/Additional.lyx @@ -19148,6 +19148,109 @@ co -f -u<version> <file-name> \begin_layout Subsubsection \family sans +Copy +\end_layout + +\begin_layout Standard +This will create a copy of the current document. + Since RCS does not support copy operations natively, the version history + is not preserved, and the copy is added as a new file. + It requires a clean document without any changes since the last checkin. + You are asked for a file name and a description of the copy operation. + After that the copy is created, both locally and in the repository. + If the parent directories of the copied and original document differ, all + relative paths of included files of the copy are adjusted (like in +\family sans +File\SpecialChar \menuseparator +Save As +\family default +\SpecialChar \ldots{} +). + Finally, the copy is loaded instead of the original document. +\end_layout + +\begin_layout Labeling +\labelwidthstring 00.00.0000 +RCS +\begin_inset space ~ +\end_inset + +commands: +\begin_inset space ~ +\end_inset + + +\begin_inset Newline newline +\end_inset + +Copy +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\family typewriter +\begin_inset Quotes eld +\end_inset + +<file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + to +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\family typewriter +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +ci -q -u +\family typewriter +-i +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection + +\family sans Undo Last Checkin \end_layout @@ -19552,6 +19655,237 @@ cvs -q unedit "<file-name>" \end_layout \begin_layout Subsubsection + +\family sans +Copy +\end_layout + +\begin_layout Standard +This will create a copy of the current document. + Since CVS does not support copy operations natively, the version history + is not preserved, and the copy is added as a new file. + It requires a clean document without any changes since the last checkin. + You are asked for a file name and a description of the copy operation. + After that the copy is created, both locally and in the repository. + If the parent directories of the copied and original document differ, all + relative paths of included files of the copy are adjusted (like in +\family sans +File\SpecialChar \menuseparator +Save As +\family default +\SpecialChar \ldots{} +). + Finally, the copy is loaded instead of the original document. +\end_layout + +\begin_layout Labeling +\labelwidthstring 00.00.0000 +CVS +\begin_inset space ~ +\end_inset + +commands: +\begin_inset space ~ +\end_inset + + +\begin_inset Newline newline +\end_inset + +Copy +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\family typewriter +\begin_inset Quotes eld +\end_inset + +<file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + to +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\family typewriter +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +cvs -q add +\family typewriter + +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection + +\family sans +Rename +\end_layout + +\begin_layout Standard +This will rename the current document. + Since CVS does not support rename operations natively, the version history + is not preserved, the renamed document is added as a new file, and the + original document is deleted. + It requires a clean document without any changes since the last checkin. + You are asked for a file name and a description of the rename operation. + After that the document is renamed, both locally and in the repository. + If the parent directories of the new and old file names differ, all relative + paths of included files are adjusted (like in +\family sans +File\SpecialChar \menuseparator +Save As +\family default +\SpecialChar \ldots{} +). + Finally, the document is reloaded using the new name. +\end_layout + +\begin_layout Labeling +\labelwidthstring 00.00.0000 +CVS +\begin_inset space ~ +\end_inset + +commands: +\begin_inset space ~ +\end_inset + + +\begin_inset Newline newline +\end_inset + +Rename +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\family typewriter +\begin_inset Quotes eld +\end_inset + +<file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + to +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout + +\family typewriter +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +cvs -q add +\family typewriter + +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +cvs -q remove +\family typewriter + +\begin_inset Quotes eld +\end_inset + +<file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection Update of the local directory checkout from repository \end_layout @@ -19929,6 +20263,168 @@ svn revert -q \end_layout \begin_layout Subsubsection + +\family sans +Copy +\end_layout + +\begin_layout Standard +This will create a copy of the current document including the version history. + It requires a clean document without any changes since the last checkin. + You are asked for a file name and a description of the copy operation. + After that the copy is created, both locally and in the repository. + If the parent directories of the copied and original document differ, all + relative paths of included files of the copy are adjusted (like in +\family sans +File\SpecialChar \menuseparator +Save As +\family default +\SpecialChar \ldots{} +). + Finally, the copy is loaded instead of the original document. +\end_layout + +\begin_layout Labeling +\labelwidthstring 00.00.0000 +SVN +\begin_inset space ~ +\end_inset + +commands: +\begin_inset space ~ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +svn copy -q +\family typewriter + +\begin_inset Quotes eld +\end_inset + +<file-name> +\begin_inset Quotes erd +\end_inset + + +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +svn commit +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection + +\family sans +Rename +\end_layout + +\begin_layout Standard +This will rename the current document including the version history. + It requires a clean document without any changes since the last checkin. + You are asked for a file name and a description of the rename operation. + After that the document is renamed, both locally and in the repository. + If the parent directories of the new and old file names differ, all relative + paths of included files are adjusted (like in +\family sans +File\SpecialChar \menuseparator +Save As +\family default +\SpecialChar \ldots{} +). + Finally, the document is reloaded using the new name. +\end_layout + +\begin_layout Labeling +\labelwidthstring 00.00.0000 +SVN +\begin_inset space ~ +\end_inset + +commands: +\begin_inset space ~ +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +svn move -q +\family typewriter + +\begin_inset Quotes eld +\end_inset + +<file-name> +\begin_inset Quotes erd +\end_inset + + +\begin_inset Quotes eld +\end_inset + +<new-file-name> +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\end_inset + + +\begin_inset Newline newline +\end_inset + + +\begin_inset Flex Code +status collapsed + +\begin_layout Plain Layout +svn commit +\end_layout + +\end_inset + + +\end_layout + +\begin_layout Subsubsection \begin_inset CommandInset label LatexCommand label name "sub:SVN-Repo-Update" diff --git a/lib/doc/LFUNs.lyx b/lib/doc/LFUNs.lyx index 127775f..45b391d 100644 --- a/lib/doc/LFUNs.lyx +++ b/lib/doc/LFUNs.lyx @@ -83,7 +83,7 @@ \begin_body \begin_layout Section* -LFUNs documentation automatically generated 2013-02-03 +LFUNs documentation automatically generated 2013-02-05 \end_layout \begin_layout Standard @@ -4143,6 +4143,68 @@ Origin Lgb, 1 Jul 1997 \end_layout \begin_layout Subsection* +LFUN_VC_RENAME +\end_layout + +\begin_layout Description +Action Renames the document to another name. +\end_layout + +\begin_layout Description +Notion Renaming with revision history is only supported by SVN. + For CVS it is simulated by adding the document under a new name and deleting + the old one. + For RCS it is not supported. + Disabled if uncommitted changes exist. +\end_layout + +\begin_layout Description +Syntax vc-rename <FILENAME> +\end_layout + +\begin_layout Description +Params <FILENAME>: New name of the document. +\begin_inset Newline newline +\end_inset + +A file dialog is opened if no filename is given. +\end_layout + +\begin_layout Description +Origin gb, 05 Feb 2013 +\end_layout + +\begin_layout Subsection* +LFUN_VC_COPY +\end_layout + +\begin_layout Description +Action Copies the document to another name. +\end_layout + +\begin_layout Description +Notion Copying with revision history is only supported by SVN. + For RCS and CVS it is simulated by adding the document under a new name. + Disabled if uncommitted changes exist. +\end_layout + +\begin_layout Description +Syntax vc-copy <FILENAME> +\end_layout + +\begin_layout Description +Params <FILENAME>: New name of the document. +\begin_inset Newline newline +\end_inset + +A file dialog is opened if no filename is given. +\end_layout + +\begin_layout Description +Origin gb, 05 Feb 2013 +\end_layout + +\begin_layout Subsection* LFUN_VC_CHECK_IN \end_layout diff --git a/lib/ui/stdmenus.inc b/lib/ui/stdmenus.inc index ad8e541..f1d1af4 100644 --- a/lib/ui/stdmenus.inc +++ b/lib/ui/stdmenus.inc @@ -74,6 +74,8 @@ Menuset OptItem "Register...|R" "vc-register" OptItem "Check In Changes...|I" "vc-check-in" OptItem "Check Out for Edit|O" "vc-check-out" + OptItem "Copy|p" "vc-copy" + OptItem "Rename|R" "vc-rename" OptItem "Update Local Directory From Repository|d" "vc-repo-update" OptItem "Revert to Repository Version|v" "vc-revert" OptItem "Undo Last Check In|U" "vc-undo-last" diff --git a/src/FuncCode.h b/src/FuncCode.h index 8b8e874..d8f48eb 100644 --- a/src/FuncCode.h +++ b/src/FuncCode.h @@ -453,6 +453,9 @@ enum FuncCode LFUN_BRANCH_MASTER_ACTIVATE, // spitz 20120930 LFUN_BRANCH_MASTER_DEACTIVATE, // spitz 20120930 LFUN_ENVIRONMENT_SPLIT, // spitz 20121223 + LFUN_VC_RENAME, // gb 20130205 + LFUN_VC_COPY, // gb 20130205 + // 355 LFUN_LASTACTION // end of the table }; diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index 39a5ff7..b2f5c8f 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -2147,6 +2147,34 @@ void LyXAction::init() */ { LFUN_VC_REGISTER, "vc-register", ReadOnly, System }, /*! + * \var lyx::FuncCode lyx::LFUN_VC_RENAME + * \li Action: Renames the document to another name. + * \li Notion: Renaming with revision history is only supported by SVN. + For CVS it is simulated by adding the document under a new + name and deleting the old one. For RCS it is not supported. + Disabled if uncommitted changes exist. + * \li Syntax: vc-rename <FILENAME> + * \li Params: <FILENAME>: New name of the document.\n + * A file dialog is opened if no filename is given. + * \li Origin: gb, 05 Feb 2013 + * \endvar + */ + { LFUN_VC_RENAME, "vc-rename", ReadOnly, System }, +/*! + * \var lyx::FuncCode lyx::LFUN_VC_COPY + * \li Action: Copies the document to another name. + * \li Notion: Copying with revision history is only supported by SVN. + For RCS and CVS it is simulated by adding the document + under a new name. + Disabled if uncommitted changes exist. + * \li Syntax: vc-copy <FILENAME> + * \li Params: <FILENAME>: New name of the document.\n + * A file dialog is opened if no filename is given. + * \li Origin: gb, 05 Feb 2013 + * \endvar + */ + { LFUN_VC_COPY, "vc-copy", ReadOnly, System }, +/*! * \var lyx::FuncCode lyx::LFUN_VC_CHECK_IN * \li Action: Checks-in/commits the changes of the registered file to the repository. * \li Notion: In RCS case this also unlocks the file. diff --git a/src/LyXVC.cpp b/src/LyXVC.cpp index ff64859..4f6492e 100644 --- a/src/LyXVC.cpp +++ b/src/LyXVC.cpp @@ -173,6 +173,44 @@ bool LyXVC::registrer() } +string LyXVC::rename(FileName const & fn) +{ + LYXERR(Debug::LYXVC, "LyXVC: rename"); + if (!vcs || fileInVC(fn)) + return string(); + docstring response; + bool ok = Alert::askForText(response, _("LyX VC: Log message"), + _("(no log message)")); + if (!ok) { + LYXERR(Debug::LYXVC, "LyXVC: user cancelled"); + return string(); + } + if (response.empty()) + response = _("(no log message)"); + string ret = vcs->rename(fn, to_utf8(response)); + return ret; +} + + +string LyXVC::copy(FileName const & fn) +{ + LYXERR(Debug::LYXVC, "LyXVC: copy"); + if (!vcs || fileInVC(fn)) + return string(); + docstring response; + bool ok = Alert::askForText(response, _("LyX VC: Log message"), + _("(no log message)")); + if (!ok) { + LYXERR(Debug::LYXVC, "LyXVC: user cancelled"); + return string(); + } + if (response.empty()) + response = _("(no log message)"); + string ret = vcs->copy(fn, to_utf8(response)); + return ret; +} + + LyXVC::CommandResult LyXVC::checkIn(string & log) { LYXERR(Debug::LYXVC, "LyXVC: checkIn"); @@ -273,6 +311,7 @@ string LyXVC::toggleReadOnly() return log; } case VCS::NOLOCKING: + case VCS::UNVERSIONED: break; } return string(); @@ -282,7 +321,7 @@ string LyXVC::toggleReadOnly() bool LyXVC::inUse() const { if (vcs) - return true; + return vcs->status() != VCS::UNVERSIONED; return false; } @@ -328,6 +367,20 @@ string LyXVC::revisionInfo(RevisionInfo const info) const } +bool LyXVC::renameEnabled() const +{ + if (!inUse()) + return false; + return vcs->renameEnabled(); +} + + +bool LyXVC::copyEnabled() const +{ + return inUse(); +} + + bool LyXVC::checkOutEnabled() const { return vcs && vcs->checkOutEnabled(); @@ -340,6 +393,12 @@ bool LyXVC::checkInEnabled() const } +bool LyXVC::isCheckInWithConfirmation() const +{ + return vcs && vcs->isCheckInWithConfirmation(); +} + + bool LyXVC::lockingToggleEnabled() const { return vcs && vcs->lockingToggleEnabled(); diff --git a/src/LyXVC.h b/src/LyXVC.h index 64ad303..9b1c747 100644 --- a/src/LyXVC.h +++ b/src/LyXVC.h @@ -84,11 +84,22 @@ public: // by the next multiple messages on the top of the processed dispatch // machinery. + /// + std::string rename(support::FileName const &); + /// Does the current VC support this operation? + bool renameEnabled() const; + /// + std::string copy(support::FileName const &); + /// Does the current VC support this operation? + bool copyEnabled() const; + /// Unlock and commit changes. /// \p log is non-empty on success and may be empty on failure. CommandResult checkIn(std::string & log); /// Does the current VC support this operation? bool checkInEnabled() const; + /// Should a log message be provided for next checkin? + bool isCheckInWithConfirmation() const; /// Lock/update and prepare to edit document. Returns log. std::string checkOut(); @@ -146,6 +157,7 @@ public: std::string toggleReadOnly(); /// Is the document under administration by VCS? + /// returns false for unregistered documents in a path managed by VCS bool inUse() const; /// Returns the RCS + version number for messages diff --git a/src/VCBackend.cpp b/src/VCBackend.cpp index 204c1fb..e4bc3f2 100644 --- a/src/VCBackend.cpp +++ b/src/VCBackend.cpp @@ -233,6 +233,35 @@ void RCS::registrer(string const & msg) } +bool RCS::renameEnabled() +{ + return false; +} + + +string RCS::rename(support::FileName const & /*newFile*/, string const & /*msg*/) +{ + // not implemented, since a left-over file.lyx,v would be confusing. + return string(); +} + + +string RCS::copy(support::FileName const & newFile, string const & msg) +{ + // RCS has no real copy command, so we create a poor mans version + support::FileName const oldFile(owner_->absFileName()); + if (!oldFile.copyTo(newFile)) + return string(); + FileName path(oldFile.onlyPath()); + string relFile(to_utf8(newFile.relPath(path.absFileName()))); + string cmd = "ci -q -u -i -t-\""; + cmd += msg; + cmd += "\" "; + cmd += quoteName(relFile); + return doVCCommand(cmd, path) ? string() : "RCS: Proceeded"; +} + + LyXVC::CommandResult RCS::checkIn(string const & msg, string & log) { int ret = doVCCommand("ci -q -u -m\"" + msg + "\" " @@ -369,7 +398,7 @@ bool RCS::toggleReadOnlyEnabled() // This got broken somewhere along lfuns dispatch reorganization. // reloadBuffer would be needed after this, but thats problematic // since we are inside Buffer::dispatch. - // return true; + // return return status() != UNVERSIONED; return false; } @@ -518,6 +547,7 @@ void CVS::scanMaster() LYXERR(Debug::LYXVC, "\tlooking for `" << tmpf << '\''); string line; static regex const reg("/(.*)/(.*)/(.*)/(.*)/(.*)"); + vcstatus = UNVERSIONED; while (getline(ifs, line)) { LYXERR(Debug::LYXVC, "\t line: " << line); if (contains(line, tmpf)) { @@ -711,6 +741,39 @@ void CVS::registrer(string const & msg) } +bool CVS::renameEnabled() +{ + return true; +} + + +string CVS::rename(support::FileName const & newFile, string const & msg) +{ + // CVS has no real rename command, so we create a poor mans version + support::FileName const oldFile(owner_->absFileName()); + string ret = copy(newFile, msg); + if (ret.empty()) + return ret; + string cmd = "cvs -q remove -m \"" + msg + "\" " + + quoteName(oldFile.onlyFileName()); + FileName path(oldFile.onlyPath()); + return doVCCommand(cmd, path) ? string() : ret; +} + + +string CVS::copy(support::FileName const & newFile, string const & msg) +{ + // CVS has no real copy command, so we create a poor mans version + support::FileName const oldFile(owner_->absFileName()); + if (!oldFile.copyTo(newFile)) + return string(); + FileName path(oldFile.onlyPath()); + string relFile(to_utf8(newFile.relPath(path.absFileName()))); + string cmd("cvs -q add -m \"" + msg + "\" " + quoteName(relFile)); + return doVCCommand(cmd, path) ? string() : "CVS: Proceeded"; +} + + void CVS::getDiff(OperationMode opmode, FileName const & tmpf) { doVCCommandWithOutput("cvs diff " + getTarget(opmode), @@ -1097,14 +1160,18 @@ FileName const SVN::findFile(FileName const & file) void SVN::scanMaster() { - // vcstatus code is somewhat superflous, until we want - // to implement read-only toggle for svn. - vcstatus = NOLOCKING; - if (checkLockMode()) { - if (isLocked()) { - vcstatus = LOCKED; - } else { - vcstatus = UNLOCKED; + // vcstatus code other than UNVERSIONED is somewhat superflous, + // until we want to implement read-only toggle for svn. + FileName f = findFile(owner_->fileName()); + if (f.empty()) { + vcstatus = UNVERSIONED; + } else { + vcstatus = NOLOCKING; + if (checkLockMode()) { + if (isLocked()) + vcstatus = LOCKED; + else + vcstatus = UNLOCKED; } } } @@ -1166,8 +1233,76 @@ void SVN::registrer(string const & /*msg*/) } +bool SVN::renameEnabled() +{ + return true; +} + + +string SVN::rename(support::FileName const & newFile, string const & msg) +{ + // svn move does not require a log message, since it does not commit. + // In LyX we commit immediately afterwards, otherwise it could be + // confusing to the user to have two uncommitted files. + FileName path(owner_->filePath()); + string relFile(to_utf8(newFile.relPath(path.absFileName()))); + string cmd("svn move -q " + quoteName(onlyFileName(owner_->absFileName())) + + ' ' + quoteName(relFile)); + if (doVCCommand(cmd, path)) { + cmd = "svn revert -q " + + quoteName(onlyFileName(owner_->absFileName())) + ' ' + + quoteName(relFile); + doVCCommand(cmd, path); + if (newFile.exists()) + newFile.removeFile(); + return string(); + } + vector<support::FileName> f; + f.push_back(owner_->fileName()); + f.push_back(newFile); + string log; + if (checkIn(f, msg, log) != LyXVC::Success) { + cmd = "svn revert -q " + + quoteName(onlyFileName(owner_->absFileName())) + ' ' + + quoteName(relFile); + doVCCommand(cmd, path); + if (newFile.exists()) + newFile.removeFile(); + return string(); + } + return log; +} + + +string SVN::copy(support::FileName const & newFile, string const & msg) +{ + // svn copy does not require a log message, since it does not commit. + // In LyX we commit immediately afterwards, otherwise it could be + // confusing to the user to have an uncommitted file. + FileName path(owner_->filePath()); + string relFile(to_utf8(newFile.relPath(path.absFileName()))); + string cmd("svn copy -q " + quoteName(onlyFileName(owner_->absFileName())) + + ' ' + quoteName(relFile)); + if (doVCCommand(cmd, path)) + return string(); + vector<support::FileName> f(1, newFile); + string log; + if (checkIn(f, msg, log) == LyXVC::Success) + return log; + return string(); +} + + LyXVC::CommandResult SVN::checkIn(string const & msg, string & log) { + vector<support::FileName> f(1, owner_->fileName()); + return checkIn(f, msg, log); +} + + +LyXVC::CommandResult +SVN::checkIn(vector<support::FileName> const & f, string const & msg, string & log) +{ FileName tmpf = FileName::tempName("lyxvcout"); if (tmpf.empty()){ LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); @@ -1177,7 +1312,8 @@ LyXVC::CommandResult SVN::checkIn(string const & msg, string & log) ostringstream os; os << "svn commit -m \"" << msg << '"'; - os << ' ' << quoteName(onlyFileName(owner_->absFileName())); + for (size_t i = 0; i < f.size(); ++i) + os << ' ' << quoteName(f[i].onlyFileName()); os << " > " << quoteName(tmpf.toFilesystemEncoding()); LyXVC::CommandResult ret = doVCCommand(os.str(), FileName(owner_->filePath())) ? diff --git a/src/VCBackend.h b/src/VCBackend.h index 771d20f..a888266 100644 --- a/src/VCBackend.h +++ b/src/VCBackend.h @@ -16,6 +16,7 @@ #include "support/FileName.h" #include <string> +#include <vector> #include "LyXVC.h" @@ -31,7 +32,10 @@ public: enum VCStatus { UNLOCKED, LOCKED, - NOLOCKING + NOLOCKING, + /// This file is not in version control, but it could be aded + /// (because the path is under version control) + UNVERSIONED, }; VCS(Buffer * b) : owner_(b) {} @@ -39,6 +43,12 @@ public: /// register a file for version control virtual void registrer(std::string const & msg) = 0; + /// can this operation be processed in the current VCS? + virtual bool renameEnabled() = 0; + /// rename a file. Return non-empty log on success, empty log on failure. + virtual std::string rename(support::FileName const &, std::string const &) = 0; + /// copy a file. Return non-empty log on success, empty log on failure. + virtual std::string copy(support::FileName const &, std::string const &) = 0; /// check in the current revision. /// \p log is non-empty on success and may be empty on failure. virtual LyXVC::CommandResult @@ -142,6 +152,12 @@ public: virtual void registrer(std::string const & msg); + virtual bool renameEnabled(); + + virtual std::string rename(support::FileName const &, std::string const &); + + virtual std::string copy(support::FileName const &, std::string const &); + virtual LyXVC::CommandResult checkIn(std::string const & msg, std::string & log); @@ -217,6 +233,12 @@ public: virtual void registrer(std::string const & msg); + virtual bool renameEnabled(); + + virtual std::string rename(support::FileName const &, std::string const &); + + virtual std::string copy(support::FileName const &, std::string const &); + virtual LyXVC::CommandResult checkIn(std::string const & msg, std::string & log); @@ -347,6 +369,12 @@ public: virtual void registrer(std::string const & msg); + virtual bool renameEnabled(); + + virtual std::string rename(support::FileName const &, std::string const &); + + virtual std::string copy(support::FileName const &, std::string const &); + virtual LyXVC::CommandResult checkIn(std::string const & msg, std::string & log); @@ -398,6 +426,9 @@ protected: bool isLocked() const; /// acquire/release write lock for the current file bool fileLock(bool lock, support::FileName const & tmpf, std::string & status); + /// Check in files \p f with log \p msg + LyXVC::CommandResult checkIn(std::vector<support::FileName> const & f, + std::string const & msg, std::string & log); private: /// is the loaded file under locking policy? diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index 05c34cb..4ea9e79 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -1804,6 +1804,12 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) case LFUN_VC_REGISTER: enable = doc_buffer && !doc_buffer->lyxvc().inUse(); break; + case LFUN_VC_RENAME: + enable = doc_buffer && doc_buffer->lyxvc().renameEnabled(); + break; + case LFUN_VC_COPY: + enable = doc_buffer && doc_buffer->lyxvc().copyEnabled(); + break; case LFUN_VC_CHECK_IN: enable = doc_buffer && doc_buffer->lyxvc().checkInEnabled(); break; @@ -2209,7 +2215,7 @@ void GuiView::insertLyXFile(docstring const & fname) } -bool GuiView::renameBuffer(Buffer & b, docstring const & newname) +bool GuiView::renameBuffer(Buffer & b, docstring const & newname, RenameKind kind) { FileName fname = b.fileName(); FileName const oldname = fname; @@ -2263,26 +2269,73 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname) int const ret = Alert::prompt(_("Chosen File Already Open"), text, 0, 1, _("&Rename"), _("&Cancel")); switch (ret) { - case 0: return renameBuffer(b, docstring()); + case 0: return renameBuffer(b, docstring(), kind); case 1: return false; } //return false; } - - if (FileName(fname).exists()) { + + bool const existsLocal = fname.exists(); + bool const existsInVC = LyXVC::fileInVC(fname); + if (existsLocal || existsInVC) { docstring const file = makeDisplayPath(fname.absFileName(), 30); - docstring const text = bformat(_("The document %1$s already " - "exists.\n\nDo you want to " - "overwrite that document?"), - file); - int const ret = Alert::prompt(_("Overwrite document?"), - text, 0, 2, _("&Overwrite"), _("&Rename"), _("&Cancel")); - switch (ret) { - case 0: break; - case 1: return renameBuffer(b, docstring()); - case 2: return false; + if (kind != LV_WRITE_AS && existsInVC) { + // renaming to a name that is already in VC + // would not work + docstring text = bformat(_("The document %1$s " + "is already registered.\n\n" + "Do you want to choose a new name?"), + file); + docstring const title = (kind == LV_VC_RENAME) ? + _("Rename document?") : _("Copy document?"); + docstring const button = (kind == LV_VC_RENAME) ? + _("&Rename") : _("&Copy"); + int const ret = Alert::prompt(title, text, 0, 1, + button, _("&Cancel")); + switch (ret) { + case 0: return renameBuffer(b, docstring(), kind); + case 1: return false; + } } + + if (existsLocal) { + docstring text = bformat(_("The document %1$s " + "already exists.\n\n" + "Do you want to overwrite that document?"), + file); + int const ret = Alert::prompt(_("Overwrite document?"), + text, 0, 2, _("&Overwrite"), + _("&Rename"), _("&Cancel")); + switch (ret) { + case 0: break; + case 1: return renameBuffer(b, docstring(), kind); + case 2: return false; + } + } + } + + switch (kind) { + case LV_VC_RENAME: { + string msg = b.lyxvc().rename(fname); + if (msg.empty()) + return false; + message(from_utf8(msg)); + break; } + case LV_VC_COPY: { + string msg = b.lyxvc().copy(fname); + if (msg.empty()) + return false; + message(from_utf8(msg)); + break; + } + case LV_WRITE_AS: + break; + } + // LyXVC created the file already in case of LV_VC_RENAME or + // LV_VC_COPY, but call saveBuffer() nevertheless to get + // relative paths of included stuff right if we moved e.g. from + // /a/b.lyx to /a/c/b.lyx. bool const saved = saveBuffer(b, fname); if (saved) @@ -2412,7 +2465,7 @@ bool GuiView::saveBuffer(Buffer & b, FileName const & fn) return false; } - return saveBuffer(b); + return saveBuffer(b, fn); } @@ -2809,6 +2862,36 @@ void GuiView::dispatchVC(FuncRequest const & cmd, DispatchResult & dr) } break; + case LFUN_VC_RENAME: + case LFUN_VC_COPY: { + if (!buffer || !ensureBufferClean(buffer)) + break; + if (buffer->lyxvc().inUse() && !buffer->isReadonly()) { + if (buffer->lyxvc().isCheckInWithConfirmation()) { + // Some changes are not yet committed. + // We test here and not in getStatus(), since + // this test is expensive. + string log; + LyXVC::CommandResult ret = + buffer->lyxvc().checkIn(log); + dr.setMessage(log); + if (ret == LyXVC::ErrorCommand || + ret == LyXVC::Success) + reloadBuffer(*buffer); + if (buffer->lyxvc().isCheckInWithConfirmation()) { + frontend::Alert::error( + _("Revision control error."), + _("Document could not be checked in.")); + break; + } + } + RenameKind const kind = (cmd.action() == LFUN_VC_RENAME) ? + LV_VC_RENAME : LV_VC_COPY; + renameBuffer(*buffer, cmd.argument(), kind); + } + break; + } + case LFUN_VC_CHECK_IN: if (!buffer || !ensureBufferClean(buffer)) break; @@ -3606,6 +3689,8 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; case LFUN_VC_REGISTER: + case LFUN_VC_RENAME: + case LFUN_VC_COPY: case LFUN_VC_CHECK_IN: case LFUN_VC_CHECK_OUT: case LFUN_VC_REPO_UPDATE: diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h index dff2fb6..aa03b84 100644 --- a/src/frontends/qt4/GuiView.h +++ b/src/frontends/qt4/GuiView.h @@ -355,6 +355,8 @@ private: /// bool exportBufferAs(Buffer & b); + /// + enum RenameKind { LV_WRITE_AS, LV_VC_RENAME, LV_VC_COPY }; /// Save a buffer as a new file. /** Write a buffer to a new file name and rename the buffer @@ -369,8 +371,14 @@ private: If 'newname' is non-empty and has an absolute path, that is used. Otherwise the base directory of the buffer is used as the base for any relative path in 'newname'. - */ - bool renameBuffer(Buffer & b, docstring const & newname); + + \p kind controls what is done besides the pure renaming: + * LV_WRITE_AS => The buffer is written without version control actions. + * LV_VC_RENAME => The file is renamed in version control. + * LV_VC_COPY => The file is copied in version control. + */ + bool renameBuffer(Buffer & b, docstring const & newname, + RenameKind kind = LV_WRITE_AS); /// bool saveBuffer(Buffer & b); /// save and rename buffer to fn. If fn is empty, the buffer commit 067fbe49cdc29e1d62cd5379f215b9bcb412bff0 Author: Georg Baum <[email protected]> Date: Tue Feb 5 21:24:41 2013 +0100 Correctly delete temp files FileName::erase() only clears the file name, if you want to delete the file you need to call FileName::removeFile(). diff --git a/src/VCBackend.cpp b/src/VCBackend.cpp index aa62f11..204c1fb 100644 --- a/src/VCBackend.cpp +++ b/src/VCBackend.cpp @@ -269,7 +269,7 @@ bool RCS::isCheckInWithConfirmation() FileName(owner_->filePath())); docstring diff = tmpf.fileContents("UTF-8"); - tmpf.erase(); + tmpf.removeFile(); if (diff.empty()) return false; @@ -845,7 +845,7 @@ string CVS::checkOut() rc = 0; } - tmpf.erase(); + tmpf.removeFile(); return rc ? string() : log.empty() ? "CVS: Proceeded" : "CVS: " + log; } @@ -1195,7 +1195,7 @@ LyXVC::CommandResult SVN::checkIn(string const & msg, string & log) if (!fileLock(false, tmpf, log)) ret = LyXVC::ErrorCommand; - tmpf.erase(); + tmpf.removeFile(); if (!log.empty()) log.insert(0, "SVN: "); if (ret == LyXVC::Success && log.empty()) @@ -1228,7 +1228,7 @@ bool SVN::isCheckInWithConfirmation() FileName(owner_->filePath())); docstring diff = tmpf.fileContents("UTF-8"); - tmpf.erase(); + tmpf.removeFile(); if (diff.empty()) return false; @@ -1324,7 +1324,7 @@ string SVN::checkOut() fileLock(true, tmpf, log); - tmpf.erase(); + tmpf.removeFile(); return log.empty() ? string() : "SVN: " + log; } @@ -1367,7 +1367,7 @@ string SVN::repoUpdate() hideDialogs("file", 0); } if (ret == 1 ) { - tmpf.erase(); + tmpf.removeFile(); return string(); } } @@ -1383,7 +1383,7 @@ string SVN::repoUpdate() res += "Update log:\n" + tmpf.fileContents("UTF-8"); LYXERR(Debug::LYXVC, res); - tmpf.erase(); + tmpf.removeFile(); return to_utf8(res); } @@ -1424,7 +1424,7 @@ string SVN::lockingToggle() if (ret) return string(); - tmpf.erase(); + tmpf.removeFile(); frontend::Alert::warning(_("SVN File Locking"), (locking ? _("Locking property unset.") : _("Locking property set.")) + "\n" + _("Do not forget to commit the locking property into the repository."), @@ -1561,7 +1561,7 @@ bool SVN::getFileRevisionInfo() } ifs.close(); - tmpf.erase(); + tmpf.removeFile(); return !rev.empty(); } @@ -1585,7 +1585,7 @@ bool SVN::getTreeRevisionInfo() string line; getline(ifs, line); ifs.close(); - tmpf.erase(); + tmpf.removeFile(); rev_tree_cache_ = line; return !line.empty(); ----------------------------------------------------------------------- Summary of changes: lib/doc/Additional.lyx | 496 +++++++++++++++++++++++++++++++++++++++++ lib/doc/LFUNs.lyx | 64 ++++++- lib/ui/stdmenus.inc | 2 + src/FuncCode.h | 3 + src/LyXAction.cpp | 28 +++ src/LyXVC.cpp | 63 +++++- src/LyXVC.h | 12 + src/VCBackend.cpp | 176 +++++++++++++-- src/VCBackend.h | 33 +++- src/frontends/qt4/GuiView.cpp | 115 +++++++++-- src/frontends/qt4/GuiView.h | 12 +- 11 files changed, 963 insertions(+), 41 deletions(-) hooks/post-receive -- The LyX Source Repository
