diff --git a/development/FORMAT b/development/FORMAT index 124e461379..1b0f3e277e 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -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 + * 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 * Format incremented to 404: refstyle support diff --git a/lib/lyx2lyx/lyx_2_0.py b/lib/lyx2lyx/lyx_2_0.py index 6e9440fa7f..1d7c8b7d72 100644 --- a/lib/lyx2lyx/lyx_2_0.py +++ b/lib/lyx2lyx/lyx_2_0.py @@ -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]], diff --git a/src/Author.cpp b/src/Author.cpp index 90c319e8a6..e88bb7f490 100644 --- a/src/Author.cpp +++ b/src/Author.cpp @@ -12,9 +12,8 @@ #include "Author.h" -#include "support/lstrings.h" - #include "support/lassert.h" +#include "support/lstrings.h" #include #include @@ -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,17 +82,17 @@ 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_++; @@ -128,24 +145,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()) diff --git a/src/Author.h b/src/Author.h index ca449381e5..afc3957691 100644 --- a/src/Author.h +++ b/src/Author.h @@ -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_; }; diff --git a/src/Buffer.cpp b/src/Buffer.cpp index feaf141f4a..209f12133c 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -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 DepClean; typedef map > RefCache; diff --git a/src/BufferParams.h b/src/BufferParams.h index abe30526bd..7a59bae753 100644 --- a/src/BufferParams.h +++ b/src/BufferParams.h @@ -340,7 +340,8 @@ public: AuthorList const & authors() const; /// map of the file's author IDs to AuthorList indexes - std::map author_map; + typedef std::map AuthorMap; + AuthorMap author_map; /// the buffer's font encoding std::string const font_encoding() const; /// diff --git a/src/Text.cpp b/src/Text.cpp index d00d2d5356..f6f75d9045 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -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 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),