# # # patch "monotone.texi" # from [5d2e2aeacc15586b5cfd80946e0b023240103b7a] # to [1d3a15d2ba9a607fd8fc6923e2de670c0a2dbffc] # # patch "selectors.cc" # from [2618e4b9b7278500400795e26275d823692d8c5b] # to [0f13a8cddbbf86ad067e16e2ca3fec2812b3f3bc] # # patch "tests/extended-selectors/__driver__.lua" # from [56708a4dc0c67cb857f5458b50a437d8b545122f] # to [4eef27537290df61cc1c5d76cadb0f5a433abca7] # ============================================================ --- monotone.texi 5d2e2aeacc15586b5cfd80946e0b023240103b7a +++ monotone.texi 1d3a15d2ba9a607fd8fc6923e2de670c0a2dbffc @@ -2896,13 +2896,13 @@ @heading Composite selectors There are also several selector functions defined, which take one or more selectors as arguments. These are: address@hidden address@hidden @code{difference(A,B)} address@hidden @code address@hidden difference(A,B) Set difference; this returns all revisions selected by A but not by B. For example, @code{difference(a:graydon,b:net.venge.monotone)} would return all revisions which have an @code{author} cert beginning with @code{graydon} which are not in the branch @code{net.venge.monotone}. address@hidden @code{lca(A,B)} address@hidden lca(A,B) Least common ancestors; this is identical to @code{max((ancestors(A)|A)/(ancestors(B)|B))}, but it may be faster and is certainly more convenient to type. For example, @@ -2910,30 +2910,30 @@ @heading Composite selectors return the last propagate between the given branches, or the branch point if there were no subsequent propagates yet. This could be particularly useful with the @code{diff} command, to see exactly what has changed on a given branch. address@hidden @code{max(A)} address@hidden max(A) Erase ancestors; this returns all revisions selected by @code{A} which are not ancestors of other revisions selected by @code{A}. For example, @code{max(b:net.venge.monotone/a:graydon)} would return the latest revision(s) on branch @code{net.venge.monotone} which have an @code{author} cert beginning with @code{graydon}. address@hidden @code{ancestors(A)} address@hidden ancestors(A) Strict ancestors; returns all revisions which are an ancestor of a revision selected by @code{A}. For example, @code{ancestors(b:net.venge.monotone)} would return all revisions in branch @code{net.venge.monotone} except for the branch heads, and all revisions in branches which have been merged back into @code{net.venge.monotone}. address@hidden @code{descendants(A)} address@hidden descendants(A) Strict descendants; returns all revisions which are a descendant of a revision selected by @code{A}. For example, @code{descendants(b:net.venge.monotone/a:graydon)} would return all revisions which are descended from a revision which is in branch @code{net.venge.monotone} and has an @code{author} cert beginning with @code{graydon}. address@hidden @code{parents(A)} address@hidden parents(A) Returns all revisions which are a parent of a revision selected by @code{A}. For example, @code{parents(m:*foobar*)} would return the parents of any revisions which have @code{comment} or @code{changelog} certs containing the word @code{foobar}. address@hidden @code{children(A)} address@hidden children(A) Returns all revisions which are a child of a revision selected by @code{A}. For example, @code{children(m:*foobar*)} would return the children of any revisions which have @code{comment} or @code{changelog} certs containing the ============================================================ --- selectors.cc 2618e4b9b7278500400795e26275d823692d8c5b +++ selectors.cc 0f13a8cddbbf86ad067e16e2ca3fec2812b3f3bc @@ -435,9 +435,15 @@ set get_ancestors(project_t frontier.erase(frontier.begin()); set p; project.db.get_revision_parents(revid, p); - p.erase(revision_id()); - frontier.insert(p.begin(), p.end()); - ret.insert(p.begin(), p.end()); + for (set::const_iterator i = p.begin(); + i != p.end(); ++i) + { + if (null_id(*i)) + continue; + pair::iterator, bool> x = ret.insert(*i); + if (x.second) + frontier.insert(*i); + } } return ret; } @@ -510,8 +516,15 @@ public: frontier.erase(frontier.begin()); set c; project.db.get_revision_children(revid, c); - frontier.insert(c.begin(), c.end()); - ret.insert(c.begin(), c.end()); + for (set::const_iterator i = c.begin(); + i != c.end(); ++i) + { + if (null_id(*i)) + continue; + pair::iterator, bool> x = ret.insert(*i); + if (x.second) + frontier.insert(*i); + } } return ret; } ============================================================ --- tests/extended-selectors/__driver__.lua 56708a4dc0c67cb857f5458b50a437d8b545122f +++ tests/extended-selectors/__driver__.lua 4eef27537290df61cc1c5d76cadb0f5a433abca7 @@ -89,4 +89,4 @@ expect("max((ancestors(h:testbranch)|h:t other_head = merge(other_2, m, "otherbranch", "Jack") expect("max((ancestors(h:testbranch)|h:testbranch)/(ancestors(h:otherbranch)|h:otherbranch))", m) -expect("lca(h:testbranch,h:otherbranch)", m) \ No newline at end of file +expect("lca(h:testbranch,h:otherbranch)", m)