mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-12 22:14:35 +00:00
Fix bug #6058: Change tracking and versioning.
Computes a hash value for the authors when using change tracking. Text.cpp, BufferParams.h, Author.h: Change unsigned int to int because the hash values can be negative. lyx2lyx: Allow to convert negative author_ids. See also: r30756. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@36134 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
fb64f0e1af
commit
f226c9d3fc
@ -6,6 +6,13 @@ changes happened in particular if possible.
|
|||||||
The good example would be 2010-01-10 entry.
|
The good example would be 2010-01-10 entry.
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
|
2010-10-23 Vincent van Ravesteijn <vfr@lyx.org>
|
||||||
|
* Format incremented to 405: author hash numbers
|
||||||
|
The authors that are used in change tracking are
|
||||||
|
now identified in the file by a number that represents
|
||||||
|
the hash value of the name and email. In this way
|
||||||
|
collaboration using version control leads to way less
|
||||||
|
merge conflicts.
|
||||||
|
|
||||||
2010-10-13 Richard Heck <rgheck@comcast.net>
|
2010-10-13 Richard Heck <rgheck@comcast.net>
|
||||||
* Format incremented to 404: refstyle support
|
* Format incremented to 404: refstyle support
|
||||||
|
@ -771,7 +771,7 @@ def revert_author_id(document):
|
|||||||
" Remove the author_id from the \\author definition "
|
" Remove the author_id from the \\author definition "
|
||||||
i = 0
|
i = 0
|
||||||
anum = 0
|
anum = 0
|
||||||
rx = re.compile(r'(\\author)\s+(\d+)\s+(\".*\")\s*(.*)$')
|
rx = re.compile(r'(\\author)\s+([-\d]+)\s+(\".*\")\s*(.*)$')
|
||||||
idmap = dict()
|
idmap = dict()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -2013,10 +2013,12 @@ convert = [[346, []],
|
|||||||
[401, []],
|
[401, []],
|
||||||
[402, [convert_bibtex_clearpage]],
|
[402, [convert_bibtex_clearpage]],
|
||||||
[403, [convert_flexnames]],
|
[403, [convert_flexnames]],
|
||||||
[404, [convert_prettyref]]
|
[404, [convert_prettyref]],
|
||||||
|
[405, []]
|
||||||
]
|
]
|
||||||
|
|
||||||
revert = [[403, [revert_refstyle]],
|
revert = [[404, []],
|
||||||
|
[403, [revert_refstyle]],
|
||||||
[402, [revert_flexnames]],
|
[402, [revert_flexnames]],
|
||||||
[401, []],
|
[401, []],
|
||||||
[400, [revert_diagram]],
|
[400, [revert_diagram]],
|
||||||
|
@ -12,9 +12,8 @@
|
|||||||
|
|
||||||
#include "Author.h"
|
#include "Author.h"
|
||||||
|
|
||||||
#include "support/lstrings.h"
|
|
||||||
|
|
||||||
#include "support/lassert.h"
|
#include "support/lassert.h"
|
||||||
|
#include "support/lstrings.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
@ -24,6 +23,24 @@ using namespace lyx::support;
|
|||||||
|
|
||||||
namespace lyx {
|
namespace lyx {
|
||||||
|
|
||||||
|
static int computeHash(docstring const & name,
|
||||||
|
docstring const & email)
|
||||||
|
{
|
||||||
|
string const full_author_string = to_ascii(name + email);
|
||||||
|
// Bernstein's hash function
|
||||||
|
unsigned int hash = 5381;
|
||||||
|
for (unsigned int i = 0; i < full_author_string.length(); ++i)
|
||||||
|
hash = ((hash << 5) + hash) + unsigned int(full_author_string[i]);
|
||||||
|
return int(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Author::Author(docstring const & name, docstring const & email)
|
||||||
|
: name_(name), email_(email), used_(true)
|
||||||
|
{
|
||||||
|
buffer_id_ = computeHash(name_, email_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool operator==(Author const & l, Author const & r)
|
bool operator==(Author const & l, Author const & r)
|
||||||
{
|
{
|
||||||
@ -65,18 +82,18 @@ AuthorList::AuthorList()
|
|||||||
|
|
||||||
int AuthorList::record(Author const & a)
|
int AuthorList::record(Author const & a)
|
||||||
{
|
{
|
||||||
|
// If we record an author which equals the current
|
||||||
|
// author, we copy the buffer_id, so that it will
|
||||||
|
// keep the same id in the file.
|
||||||
|
if (authors_.size() > 0 && a == authors_[0])
|
||||||
|
authors_[0].setBufferId(a.buffer_id());
|
||||||
|
|
||||||
Authors::const_iterator it(authors_.begin());
|
Authors::const_iterator it(authors_.begin());
|
||||||
Authors::const_iterator itend(authors_.end());
|
Authors::const_iterator itend(authors_.end());
|
||||||
|
|
||||||
for (int i = 0; it != itend; ++it, ++i) {
|
for (int i = 0; it != itend; ++it, ++i) {
|
||||||
if (*it == a) {
|
if (*it == a)
|
||||||
if (it->buffer_id() == 0)
|
|
||||||
// The current author is internally represented as
|
|
||||||
// author 0, but it appears he has already an id.
|
|
||||||
it->setBufferId(a.buffer_id());
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
authors_.push_back(a);
|
authors_.push_back(a);
|
||||||
return last_id_++;
|
return last_id_++;
|
||||||
}
|
}
|
||||||
@ -129,24 +146,6 @@ ostream & operator<<(ostream & os, AuthorList const & a) {
|
|||||||
AuthorList::Authors::const_iterator a_it = sorted.begin();
|
AuthorList::Authors::const_iterator a_it = sorted.begin();
|
||||||
AuthorList::Authors::const_iterator a_end = sorted.end();
|
AuthorList::Authors::const_iterator a_end = sorted.end();
|
||||||
|
|
||||||
// Find the buffer id for the current author (internal id 0),
|
|
||||||
// if he doesn't have a buffer_id yet.
|
|
||||||
if (sorted.get(0).buffer_id() == 0) {
|
|
||||||
unsigned int cur_id = 1;
|
|
||||||
for (; a_it != a_end; ++a_it) {
|
|
||||||
if (a_it->buffer_id() == cur_id)
|
|
||||||
++cur_id;
|
|
||||||
else if (a_it->buffer_id() > cur_id) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Set the id in both the original authorlist,
|
|
||||||
// as in the copy.
|
|
||||||
a.get(0).setBufferId(cur_id);
|
|
||||||
sorted.get(0).setBufferId(cur_id);
|
|
||||||
sorted.sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (a_it = sorted.begin(); a_it != a_end; ++a_it) {
|
for (a_it = sorted.begin(); a_it != a_end; ++a_it) {
|
||||||
if (a_it->used())
|
if (a_it->used())
|
||||||
os << "\\author " << *a_it << "\n";
|
os << "\\author " << *a_it << "\n";
|
||||||
|
@ -24,16 +24,15 @@ public:
|
|||||||
///
|
///
|
||||||
Author() {}
|
Author() {}
|
||||||
///
|
///
|
||||||
Author(docstring const & name, docstring const & email)
|
Author(docstring const & name, docstring const & email);
|
||||||
: name_(name), email_(email), used_(true), buffer_id_(0) {}
|
|
||||||
///
|
///
|
||||||
docstring name() const { return name_; }
|
docstring name() const { return name_; }
|
||||||
///
|
///
|
||||||
docstring email() const { return email_; }
|
docstring email() const { return email_; }
|
||||||
///
|
///
|
||||||
unsigned int buffer_id() const { return buffer_id_; }
|
int buffer_id() const { return buffer_id_; }
|
||||||
///
|
///
|
||||||
void setBufferId(unsigned int buffer_id) const { buffer_id_ = buffer_id; }
|
void setBufferId(int buffer_id) const { buffer_id_ = buffer_id; }
|
||||||
///
|
///
|
||||||
void setUsed(bool u) const { used_ = u; }
|
void setUsed(bool u) const { used_ = u; }
|
||||||
///
|
///
|
||||||
@ -49,7 +48,7 @@ private:
|
|||||||
///
|
///
|
||||||
mutable bool used_;
|
mutable bool used_;
|
||||||
/// The id of the author in the lyx-file
|
/// The id of the author in the lyx-file
|
||||||
mutable unsigned int buffer_id_;
|
mutable int buffer_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ namespace {
|
|||||||
|
|
||||||
// Do not remove the comment below, so we get merge conflict in
|
// Do not remove the comment below, so we get merge conflict in
|
||||||
// independent branches. Instead add your own.
|
// independent branches. Instead add your own.
|
||||||
int const LYX_FORMAT = 404; // rgh: refstyle
|
int const LYX_FORMAT = 405; // vfr: author hash
|
||||||
|
|
||||||
typedef map<string, bool> DepClean;
|
typedef map<string, bool> DepClean;
|
||||||
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
|
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
|
||||||
|
@ -340,7 +340,8 @@ public:
|
|||||||
AuthorList const & authors() const;
|
AuthorList const & authors() const;
|
||||||
|
|
||||||
/// map of the file's author IDs to AuthorList indexes
|
/// map of the file's author IDs to AuthorList indexes
|
||||||
std::map<unsigned int, int> author_map;
|
typedef std::map<int, int> AuthorMap;
|
||||||
|
AuthorMap author_map;
|
||||||
/// the buffer's font encoding
|
/// the buffer's font encoding
|
||||||
std::string const font_encoding() const;
|
std::string const font_encoding() const;
|
||||||
///
|
///
|
||||||
|
@ -456,10 +456,10 @@ void Text::readParToken(Paragraph & par, Lexer & lex,
|
|||||||
} else if (token == "\\change_inserted" || token == "\\change_deleted") {
|
} else if (token == "\\change_inserted" || token == "\\change_deleted") {
|
||||||
lex.eatLine();
|
lex.eatLine();
|
||||||
istringstream is(lex.getString());
|
istringstream is(lex.getString());
|
||||||
unsigned int aid;
|
int aid;
|
||||||
time_t ct;
|
time_t ct;
|
||||||
is >> aid >> ct;
|
is >> aid >> ct;
|
||||||
map<unsigned int, int> const & am = bp.author_map;
|
BufferParams::AuthorMap const & am = bp.author_map;
|
||||||
if (am.find(aid) == am.end()) {
|
if (am.find(aid) == am.end()) {
|
||||||
errorList.push_back(ErrorItem(_("Change tracking error"),
|
errorList.push_back(ErrorItem(_("Change tracking error"),
|
||||||
bformat(_("Unknown author index for change: %1$d\n"), aid),
|
bformat(_("Unknown author index for change: %1$d\n"), aid),
|
||||||
|
Loading…
Reference in New Issue
Block a user