Backport svn locking

http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg147723.html



git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_6_X@28817 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Pavel Sanda 2009-03-16 18:30:53 +00:00
parent cd088e64f3
commit e211a71471
6 changed files with 266 additions and 15 deletions

View File

@ -17024,7 +17024,7 @@ When you are finished editing a file, you commit your changes.
\begin_layout Standard
CVS command:
\family typewriter
cvs -q commit -m"<description>" <file-name>
cvs -q commit -m"<description>" "<file-name>"
\end_layout
\begin_layout Subsubsection
@ -17171,7 +17171,25 @@ When you are finished editing a file, you commit your changes.
\end_layout
\begin_layout Standard
SVN command:
SVN command:
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
In case locking is not enabled.
See Section
\begin_inset CommandInset ref
LatexCommand ref
reference "subsec:SVN-File-Locking"
\end_inset
.
\end_layout
\end_inset
\family typewriter
svn commit -q -m"<description>" <file-name>
\end_layout
@ -17189,7 +17207,17 @@ Updates the changes of this file from the repository.
\end_layout
\begin_layout Standard
SVN command:
SVN command:
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
Ditto.
\end_layout
\end_inset
\family typewriter
svn update
\begin_inset Quotes eld
@ -17252,6 +17280,116 @@ svn log
is shown in a browser.
\end_layout
\begin_layout Subsubsection
File Locking
\begin_inset CommandInset label
LatexCommand label
name "subsec:SVN-File-Locking"
\end_inset
\end_layout
\begin_layout Standard
The file exchange through various revision control systems brings the problem
of merge conflicts in case two different users try to edit the same (parts
of) document.
When such conflict happens it needs manual resolving and one reasonable
alternative is to provide some kind of locking mechanism, which guarantees
that only one user is allowed to edit file at the given time.
\end_layout
\begin_layout Standard
SVN has two mechanisms to provide such kind of mutual exclusivity for file
access - locks and automatical setting of write permissions based on
\begin_inset Flex CharStyle:Code
status collapsed
\begin_layout Plain Layout
svn:needs-lock
\end_layout
\end_inset
file svn property
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
http://svnbook.red-bean.com/en/1.2/svn.advanced.locking.html
\end_layout
\end_inset
.
In a case this property is detected for a given document LyX starts to
use SVN locks for document editing automatically and the whole check-in/out
mechanism switches to the same regimen as for RCS.
This in particular means there are two different modes how file is used
in LyX:
\end_layout
\begin_layout Itemize
Unlocked state.
The loaded file is in the read-only mode.
For editation on needs to check-out.
\emph on
Check-out
\emph default
consists of update from repository and gaining write lock.
If the lock is not possible to obtain, we remain in unlocked state.
\end_layout
\begin_layout Itemize
Locked state.
The loaded file is in the 'normal' edit mode.
No other user is allowed to edit the file.
\emph on
Check-in
\emph default
consists of commiting changes and releasing write-lock.
If no changes have been made to the document, no commit will be produced
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
Don't be puzzled by the fact that you will be asked for commit message anyway.
\end_layout
\end_inset
and only the write-lock will be released.
\end_layout
\begin_layout Standard
SVN commands:
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
Check-in:
\family typewriter
svn commit -q -m"<description>" "<file-name>"
\begin_inset Newline newline
\end_inset
svn unlock "<file-name>"
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
Check-out:
\family typewriter
svn update "<file-name>"
\begin_inset Newline newline
\end_inset
svn lock "<file-name>"
\end_layout
\begin_layout Subsection
SVN and Windows Environment
\end_layout

View File

@ -205,6 +205,8 @@ void LyXVC::toggleReadOnly()
LYXERR(Debug::LYXVC, "LyXVC: toggle to unlocked");
checkIn();
break;
case VCS::NOLOCKING:
break;
}
}

View File

@ -45,9 +45,13 @@ int VCS::doVCCommandCall(string const & cmd, FileName const & path){
int VCS::doVCCommand(string const & cmd, FileName const & path)
{
owner_->setBusy(true);
if (owner_)
owner_->setBusy(true);
int const ret = doVCCommandCall(cmd, path);
owner_->setBusy(false);
if (owner_)
owner_->setBusy(false);
if (ret)
frontend::Alert::error(_("Revision control error."),
bformat(_("Some problem occured while running the command:\n"
@ -415,8 +419,10 @@ bool CVS::toggleReadOnlyEnabled()
SVN::SVN(FileName const & m, FileName const & f)
{
owner_ = 0;
master_ = m;
file_ = f;
locked_mode_ = 0;
scanMaster();
}
@ -449,10 +455,57 @@ FileName const SVN::findFile(FileName const & file)
void SVN::scanMaster()
{
// if we want some locking under svn
// we need different infrastructure around
locker_ = "Unlocked";
vcstatus = UNLOCKED;
locker_.clear();
vcstatus = NOLOCKING;
if (checkLockMode()) {
if (isLocked()) {
locker_ = "Locked";
vcstatus = LOCKED;
} else {
locker_ = "Unlocked";
vcstatus = LOCKED;
}
}
}
bool SVN::checkLockMode()
{
FileName tmpf = FileName::tempName("lyxvcout");
if (tmpf.empty()){
LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
return N_("Error: Could not generate logfile.");
}
LYXERR(Debug::LYXVC, "Detecting locking mode...");
if (doVCCommandCall("svn proplist " + quoteName(file_.onlyFileName())
+ " > " + quoteName(tmpf.toFilesystemEncoding()),
file_.onlyPath()))
return false;
ifstream ifs(tmpf.toFilesystemEncoding().c_str());
string line;
bool ret = false;
while (ifs) {
getline(ifs, line);
LYXERR(Debug::LYXVC, line);
if (contains(line, "svn:needs-lock"))
ret = true;
}
LYXERR(Debug::LYXVC, "Locking enabled: " << ret);
ifs.close();
locked_mode_ = ret;
return ret;
}
bool SVN::isLocked() const
{
//refresh file info
FileName file(file_.absFilename());
return !file.isReadOnly();
}
@ -483,6 +536,9 @@ string SVN::checkIn(string const & msg)
_("Error when commiting to repository.\n"
"You have to manually resolve the problem.\n"
"After pressing OK, LyX will reopen the document."));
else
fileLock(false, tmpf, log);
tmpf.erase();
return "SVN: " + log;
}
@ -490,9 +546,13 @@ string SVN::checkIn(string const & msg)
bool SVN::checkInEnabled()
{
return true;
if (locked_mode_)
return isLocked();
else
return true;
}
// FIXME Correctly return code should be checked instead of this.
// This would need another solution than just plain startscript.
// Hint from Andre': QProcess::readAllStandardError()...
@ -515,6 +575,36 @@ string SVN::scanLogFile(FileName const & f, string & status)
}
void SVN::fileLock(bool lock, FileName const & tmpf, string &status)
{
if (!locked_mode_ || (isLocked() == lock))
return;
string arg = lock ? "lock " : "unlock ";
doVCCommand("svn "+ arg + quoteName(onlyFilename(owner_->absFileName()))
+ " > " + quoteName(tmpf.toFilesystemEncoding()),
FileName(owner_->filePath()));
ifstream ifs(tmpf.toFilesystemEncoding().c_str());
string line;
while (ifs) {
getline(ifs, line);
if (!line.empty()) status += line + "; ";
}
ifs.close();
if (!isLocked() && lock)
frontend::Alert::error(_("Revision control error."),
_("Error when acquiring write lock.\n"
"Most probably some other user edit the current document now!\n"
"Check also the access to the repository."));
if (isLocked() && !lock)
frontend::Alert::error(_("Revision control error."),
_("Error when releasing write lock.\n"
"Check the access to the repository."));
}
string SVN::checkOut()
{
FileName tmpf = FileName::tempName("lyxvcout");
@ -535,6 +625,9 @@ string SVN::checkOut()
"You have to manually resolve the conflicts NOW!\n'%1$s'.\n\n"
"After pressing OK, LyX will try to reopen resolved document."),
from_local8bit(res)));
fileLock(true, tmpf, log);
tmpf.erase();
return "SVN: " + log;
}
@ -542,7 +635,10 @@ string SVN::checkOut()
bool SVN::checkOutEnabled()
{
return true;
if (locked_mode_)
return !isLocked();
else
return true;
}

View File

@ -27,7 +27,8 @@ public:
/// the status of the managed file
enum VCStatus {
UNLOCKED,
LOCKED
LOCKED,
NOLOCKING
};
virtual ~VCS() {}
@ -225,9 +226,17 @@ protected:
virtual void scanMaster();
/// Check for messages in svn output. Returns error.
std::string scanLogFile(support::FileName const & f, std::string & status);
/// checks locking policy and setup locked_mode_
bool checkLockMode();
/// is the loaded file locked?
bool isLocked() const;
/// acquire/release write lock for the current file
void fileLock(bool lock, support::FileName const & tmpf, std::string & status);
private:
support::FileName file_;
/// is the loaded file under locking policy?
bool locked_mode_;
};
} // namespace lyx

View File

@ -1129,8 +1129,12 @@ void GuiWorkArea::updateWindowTitle()
if (!fileName.empty()) {
maximize_title = fileName.displayName(30);
minimize_title = from_utf8(fileName.onlyFileName());
if (buf.lyxvc().inUse())
maximize_title += _(" (version control)");
if (buf.lyxvc().inUse()) {
if (buf.lyxvc().locker().empty())
maximize_title += _(" (version control)");
else
maximize_title += _(" (version control, locking)");
}
if (!buf.isClean()) {
maximize_title += _(" (changed)");
minimize_title += char_type('*');

View File

@ -37,7 +37,9 @@ What's new
- Store the command buffer history in the session file and show it in
a pop-up list in the command buffer.
- Added locking capabilities for SVN version control support.
Read Extended manual for details.
* WINDOWS INSTALLER