mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-25 10:58:52 +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.
|
||||
|
||||
-----------------------
|
||||
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>
|
||||
* Format incremented to 404: refstyle support
|
||||
|
@ -771,7 +771,7 @@ def revert_author_id(document):
|
||||
" Remove the author_id from the \\author definition "
|
||||
i = 0
|
||||
anum = 0
|
||||
rx = re.compile(r'(\\author)\s+(\d+)\s+(\".*\")\s*(.*)$')
|
||||
rx = re.compile(r'(\\author)\s+([-\d]+)\s+(\".*\")\s*(.*)$')
|
||||
idmap = dict()
|
||||
|
||||
while True:
|
||||
@ -2013,10 +2013,12 @@ convert = [[346, []],
|
||||
[401, []],
|
||||
[402, [convert_bibtex_clearpage]],
|
||||
[403, [convert_flexnames]],
|
||||
[404, [convert_prettyref]]
|
||||
[404, [convert_prettyref]],
|
||||
[405, []]
|
||||
]
|
||||
|
||||
revert = [[403, [revert_refstyle]],
|
||||
revert = [[404, []],
|
||||
[403, [revert_refstyle]],
|
||||
[402, [revert_flexnames]],
|
||||
[401, []],
|
||||
[400, [revert_diagram]],
|
||||
|
@ -12,9 +12,8 @@
|
||||
|
||||
#include "Author.h"
|
||||
|
||||
#include "support/lstrings.h"
|
||||
|
||||
#include "support/lassert.h"
|
||||
#include "support/lstrings.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <istream>
|
||||
@ -24,6 +23,24 @@ using namespace lyx::support;
|
||||
|
||||
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)
|
||||
{
|
||||
@ -65,18 +82,18 @@ AuthorList::AuthorList()
|
||||
|
||||
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 itend(authors_.end());
|
||||
|
||||
for (int i = 0; it != itend; ++it, ++i) {
|
||||
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());
|
||||
if (*it == a)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
authors_.push_back(a);
|
||||
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_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) {
|
||||
if (a_it->used())
|
||||
os << "\\author " << *a_it << "\n";
|
||||
|
@ -24,16 +24,15 @@ public:
|
||||
///
|
||||
Author() {}
|
||||
///
|
||||
Author(docstring const & name, docstring const & email)
|
||||
: name_(name), email_(email), used_(true), buffer_id_(0) {}
|
||||
Author(docstring const & name, docstring const & email);
|
||||
///
|
||||
docstring name() const { return name_; }
|
||||
///
|
||||
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; }
|
||||
///
|
||||
@ -49,7 +48,7 @@ private:
|
||||
///
|
||||
mutable bool used_;
|
||||
/// 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
|
||||
// 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<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
|
||||
|
@ -340,7 +340,8 @@ public:
|
||||
AuthorList const & authors() const;
|
||||
|
||||
/// 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
|
||||
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") {
|
||||
lex.eatLine();
|
||||
istringstream is(lex.getString());
|
||||
unsigned int aid;
|
||||
int aid;
|
||||
time_t 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()) {
|
||||
errorList.push_back(ErrorItem(_("Change tracking error"),
|
||||
bformat(_("Unknown author index for change: %1$d\n"), aid),
|
||||
|
Loading…
Reference in New Issue
Block a user