2016-08-23 01:45:06 +03:00
|
|
|
// treemanifest.h - c++ declarations of a tree manifest
|
|
|
|
//
|
|
|
|
// Copyright 2016 Facebook, Inc.
|
|
|
|
//
|
|
|
|
// This software may be used and distributed according to the terms of the
|
|
|
|
// GNU General Public License version 2 or any later version.
|
|
|
|
//
|
|
|
|
// no-check-code
|
|
|
|
|
|
|
|
#ifndef REMOTEFILELOG_TREEMANIFEST_H
|
|
|
|
#define REMOTEFILELOG_TREEMANIFEST_H
|
|
|
|
|
2017-02-24 01:03:03 +03:00
|
|
|
#include <memory>
|
2016-08-23 01:45:06 +03:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2016-10-15 02:01:12 +03:00
|
|
|
#include "manifest.h"
|
2016-08-23 01:45:06 +03:00
|
|
|
#include "manifest_fetcher.h"
|
2017-03-07 22:39:46 +03:00
|
|
|
#include "../cstore/match.h"
|
2016-08-23 01:45:06 +03:00
|
|
|
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
enum FindResult {
|
|
|
|
FIND_PATH_OK,
|
|
|
|
FIND_PATH_NOT_FOUND,
|
|
|
|
FIND_PATH_CONFLICT,
|
|
|
|
FIND_PATH_WTF,
|
|
|
|
};
|
|
|
|
|
2016-09-10 01:22:42 +03:00
|
|
|
enum SetResult {
|
|
|
|
SET_OK,
|
|
|
|
SET_CONFLICT,
|
|
|
|
SET_WTF,
|
|
|
|
};
|
|
|
|
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
enum FindMode {
|
|
|
|
// walks the tree and searches for a leaf node. if the path cannot be found,
|
|
|
|
// exit with `FIND_PATH_NOT_FOUND`.
|
2016-09-06 22:10:35 +03:00
|
|
|
BASIC_WALK,
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
|
|
|
|
// walks the tree. if the intermediate paths cannot be found, create them.
|
|
|
|
// if a leaf node exists where an intermediate path node needs to be
|
|
|
|
// created, then return `FIND_PATH_CONFLICT`.
|
2016-09-06 22:10:35 +03:00
|
|
|
CREATE_IF_MISSING,
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
|
|
|
|
// walks the tree. if the path cannot be found, exit with
|
|
|
|
// `FIND_PATH_NOT_FOUND`. if the operation is successful, then check
|
|
|
|
// intermediate nodes to ensure that they still have children. any nodes
|
|
|
|
// that do not should be removed.
|
2016-09-06 22:10:35 +03:00
|
|
|
REMOVE_EMPTY_IMPLICIT_NODES,
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct FindContext {
|
|
|
|
bool invalidate_checksums;
|
|
|
|
int32_t num_leaf_node_changes;
|
|
|
|
FindMode mode;
|
|
|
|
|
|
|
|
// reuse this space when fetching manifests.
|
|
|
|
std::string nodebuffer;
|
|
|
|
|
|
|
|
// any extra data the callback needs to complete the operation.
|
|
|
|
void *extras;
|
2016-09-19 23:25:34 +03:00
|
|
|
|
|
|
|
FindContext() :
|
|
|
|
invalidate_checksums(false),
|
|
|
|
num_leaf_node_changes(0),
|
|
|
|
mode(BASIC_WALK),
|
|
|
|
extras(NULL) {
|
|
|
|
}
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
};
|
|
|
|
|
2016-08-23 01:45:06 +03:00
|
|
|
class PathIterator {
|
|
|
|
private:
|
|
|
|
std::string path;
|
|
|
|
size_t position;
|
|
|
|
public:
|
|
|
|
PathIterator(std::string path) {
|
|
|
|
this->path = path;
|
|
|
|
this->position = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool next(char const ** word, size_t *wordlen) {
|
|
|
|
if (this->isfinished()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*word = this->path.c_str() + this->position;
|
|
|
|
size_t slashoffset = this->path.find('/', this->position);
|
|
|
|
if (slashoffset == std::string::npos) {
|
|
|
|
*wordlen = this->path.length() - this->position;
|
|
|
|
} else {
|
|
|
|
*wordlen = slashoffset - this->position;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->position += *wordlen + 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isfinished() {
|
|
|
|
return this->position >= this->path.length();
|
|
|
|
}
|
[ctree] replace _treemanifest_find with treemanifest_get
Summary: treemanifest_find is now a generic method to traverse a tree (like tree_path in cfastmanifest). It manages the tree by adding and removing intermediate nodes (if requested). Unlike _treemanifest_find, it uses lower-level APIs such as findChild and addChild, which uses std::list::iterator to avoid duplication of work. Previously, we would need to traverse the entire list of children to find a child, and then if it's not found, traverse the entire list again to properly locate it. Now we just find the exact location where the child is or should be, and then save that.
Test Plan: `PYTHONPATH=~/work/mercurial/facebook-hg-rpms/remotefilelog:~/work/mercurial/facebook-hg-rpms/fb-hgext/:~/work/mercurial/facebook-hg-rpms/remotenames/:~/work/mercurial/facebook-hg-rpms/lz4revlog/ /opt/local/bin/python2.7 ~/work/mercurial/facebook-hg-rpms/hg-crew/hg --config extensions.perftest=~/work/mercurial/facebook-hg-rpms/remotefilelog/tests/perftest.py testtree --kind flat,ctree,fast --test fulliter,diff,find --build "master~5::master"`
Reviewers: #fastmanifest, durham
Reviewed By: durham
Subscribers: mjpieters, durham, mitrandir
Differential Revision: https://phabricator.intern.facebook.com/D3772947
Signature: t1:3772947:1472758787:8e8597c30f2cf1512ac7195bfa44ed62c201deb2
2016-09-06 22:09:42 +03:00
|
|
|
|
|
|
|
void getPathToPosition(const char **word, size_t *wordlen) {
|
|
|
|
*word = path.c_str();
|
|
|
|
*wordlen = this->position;
|
|
|
|
}
|
2016-08-23 01:45:06 +03:00
|
|
|
};
|
|
|
|
|
2016-09-06 22:10:35 +03:00
|
|
|
/**
|
|
|
|
* A single instance of a treemanifest.
|
|
|
|
*/
|
|
|
|
struct treemanifest {
|
2016-09-06 22:38:15 +03:00
|
|
|
// Fetcher for the manifests.
|
|
|
|
ManifestFetcher fetcher;
|
2016-09-06 22:10:35 +03:00
|
|
|
|
2016-09-11 02:32:28 +03:00
|
|
|
ManifestEntry root;
|
2016-09-06 22:10:35 +03:00
|
|
|
|
2017-02-24 01:03:03 +03:00
|
|
|
treemanifest(std::shared_ptr<Store> store, std::string rootNode) :
|
2016-09-11 02:32:28 +03:00
|
|
|
fetcher(store) {
|
|
|
|
std::string hexnode;
|
|
|
|
hexnode.reserve(HEX_NODE_SIZE);
|
|
|
|
|
|
|
|
hexfrombin(rootNode.c_str(), hexnode);
|
2016-09-18 23:40:14 +03:00
|
|
|
root.initialize(NULL, 0, hexnode.c_str(), MANIFEST_DIRECTORY_FLAGPTR);
|
2016-09-18 23:38:01 +03:00
|
|
|
|
|
|
|
// ManifestEntry.initialize will create a blank manifest in .resolved.
|
|
|
|
// however, we actually want the resolution to happen through
|
2016-10-15 02:01:12 +03:00
|
|
|
// manifestfetcher. therefore, let's clear it.
|
|
|
|
root.resolved = ManifestPtr();
|
2016-09-06 22:38:15 +03:00
|
|
|
}
|
|
|
|
|
2017-02-24 01:03:03 +03:00
|
|
|
treemanifest(std::shared_ptr<Store> store) :
|
2016-09-11 02:32:28 +03:00
|
|
|
fetcher(store) {
|
2017-04-20 07:14:04 +03:00
|
|
|
root.initialize(NULL, 0, HEXNULLID, MANIFEST_DIRECTORY_FLAGPTR);
|
2016-09-11 02:32:28 +03:00
|
|
|
}
|
2016-09-06 22:38:15 +03:00
|
|
|
|
2016-09-19 23:25:34 +03:00
|
|
|
treemanifest(treemanifest &other) :
|
|
|
|
fetcher(other.fetcher) {
|
|
|
|
root.initialize(&other.root);
|
|
|
|
}
|
2016-09-12 21:44:47 +03:00
|
|
|
|
2016-10-15 02:01:12 +03:00
|
|
|
bool get(
|
2016-09-06 22:38:15 +03:00
|
|
|
const std::string &filename,
|
2016-10-15 02:01:12 +03:00
|
|
|
std::string *resultnode, const char **resultflag,
|
|
|
|
FindResultType resulttype = RESULT_FILE);
|
2016-09-06 22:10:35 +03:00
|
|
|
|
2016-09-10 01:22:42 +03:00
|
|
|
SetResult set(
|
|
|
|
const std::string &filename,
|
2016-09-18 23:40:14 +03:00
|
|
|
const std::string &resultnode, const char *resultflag);
|
2016-09-10 01:22:42 +03:00
|
|
|
|
2016-09-10 01:24:31 +03:00
|
|
|
/**
|
|
|
|
* Removes a file from the treemanifest. Returns true iff the file was
|
|
|
|
* found and removed.
|
|
|
|
*/
|
|
|
|
bool remove(const std::string &filename);
|
|
|
|
|
2017-04-20 07:14:03 +03:00
|
|
|
Manifest *getRootManifest() {
|
2016-10-15 02:01:12 +03:00
|
|
|
if (this->root.resolved.isnull()) {
|
2016-09-11 02:32:28 +03:00
|
|
|
std::string binnode;
|
|
|
|
binnode.reserve(BIN_NODE_SIZE);
|
|
|
|
|
|
|
|
appendbinfromhex(this->root.node, binnode);
|
|
|
|
this->root.resolved = this->fetcher.get("", 0, binnode);
|
2016-09-06 22:38:15 +03:00
|
|
|
}
|
2016-09-07 23:00:55 +03:00
|
|
|
|
2016-09-11 02:32:28 +03:00
|
|
|
return this->root.resolved;
|
2016-09-06 22:38:15 +03:00
|
|
|
}
|
2016-09-06 22:38:28 +03:00
|
|
|
|
2016-09-07 23:00:55 +03:00
|
|
|
private:
|
|
|
|
|
2016-09-06 22:38:28 +03:00
|
|
|
/**
|
|
|
|
* Basic mechanism to traverse a tree. Once the deepest directory in the
|
|
|
|
* path has been located, the supplied callback is executed. That callback
|
|
|
|
* is called with the manifest of the deepest directory and the leaf node's
|
|
|
|
* filename.
|
|
|
|
*
|
|
|
|
* For instance, if treemanifest_find is called on /abc/def/ghi, then the
|
|
|
|
* callback is executed with the manifest of /abc/def, and the filename
|
|
|
|
* passed in will be "ghi".
|
|
|
|
*/
|
2016-09-06 22:38:40 +03:00
|
|
|
FindResult find(
|
2016-09-11 02:32:28 +03:00
|
|
|
ManifestEntry *manifestentry,
|
2016-09-06 22:38:28 +03:00
|
|
|
PathIterator &path,
|
|
|
|
FindMode findMode,
|
|
|
|
FindContext *findContext,
|
|
|
|
FindResult (*callback)(
|
|
|
|
Manifest *manifest,
|
|
|
|
const char *filename, size_t filenamelen,
|
2016-10-15 02:01:12 +03:00
|
|
|
FindContext *findContext,
|
|
|
|
ManifestPtr *resultManifest),
|
|
|
|
ManifestPtr *resultManifest);
|
2016-09-06 22:10:35 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a single stack frame in an iteration of the contents of the tree.
|
|
|
|
*/
|
|
|
|
struct stackframe {
|
2016-09-18 23:44:17 +03:00
|
|
|
private:
|
|
|
|
ManifestIterator iterator;
|
|
|
|
SortedManifestIterator sortedIterator;
|
2016-09-06 22:10:35 +03:00
|
|
|
|
2016-09-18 23:44:17 +03:00
|
|
|
public:
|
|
|
|
Manifest *manifest;
|
|
|
|
bool sorted;
|
|
|
|
|
|
|
|
stackframe(Manifest *manifest, bool sorted) :
|
|
|
|
manifest(manifest),
|
|
|
|
sorted(sorted) {
|
|
|
|
if (sorted) {
|
|
|
|
sortedIterator = manifest->getSortedIterator();
|
|
|
|
} else {
|
|
|
|
iterator = manifest->getIterator();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ManifestEntry *next() {
|
|
|
|
if (sorted) {
|
|
|
|
return sortedIterator.next();
|
|
|
|
} else {
|
|
|
|
return iterator.next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ManifestEntry *currentvalue() const {
|
|
|
|
if (sorted) {
|
|
|
|
return sortedIterator.currentvalue();
|
|
|
|
} else {
|
|
|
|
return iterator.currentvalue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isfinished() const {
|
|
|
|
if (sorted) {
|
|
|
|
return sortedIterator.isfinished();
|
|
|
|
} else {
|
|
|
|
return iterator.isfinished();
|
|
|
|
}
|
|
|
|
}
|
2016-09-06 22:10:35 +03:00
|
|
|
};
|
|
|
|
|
2016-09-20 22:42:23 +03:00
|
|
|
/**
|
|
|
|
* An iterator that takes a main treemanifest and a vector of comparison
|
|
|
|
* treemanifests and iterates over the Manifests that only exist in the main
|
|
|
|
* treemanifest.
|
|
|
|
*/
|
2017-04-20 07:14:03 +03:00
|
|
|
class SubtreeIterator {
|
2016-09-20 22:42:23 +03:00
|
|
|
private:
|
|
|
|
std::vector<stackframe> mainStack;
|
2017-04-26 01:44:55 +03:00
|
|
|
std::vector<const char*> cmpNodes;
|
2016-09-20 22:42:23 +03:00
|
|
|
std::vector<std::vector<stackframe> > cmpStacks;
|
|
|
|
std::string path;
|
|
|
|
ManifestFetcher fetcher;
|
|
|
|
public:
|
2017-04-20 07:14:03 +03:00
|
|
|
SubtreeIterator(Manifest *mainRoot,
|
2017-04-26 01:44:55 +03:00
|
|
|
const std::vector<const char*> &cmpNodes,
|
2016-09-20 22:42:23 +03:00
|
|
|
const std::vector<Manifest*> &cmpRoots,
|
|
|
|
const ManifestFetcher &fetcher);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Outputs the next new Manifest and its corresponding path and node.
|
|
|
|
*
|
2017-04-20 07:14:03 +03:00
|
|
|
* `resultEntry` contains the ManifestEntry that points at the result. This
|
|
|
|
* is useful for updating the ManifestEntry hash if the caller decides to
|
|
|
|
* make the result permanent.
|
|
|
|
*
|
2016-09-20 22:42:23 +03:00
|
|
|
* Return true if a manifest was returned, or false if we've reached the
|
|
|
|
* end.
|
|
|
|
*/
|
2017-04-20 07:14:03 +03:00
|
|
|
bool next(std::string **path, Manifest **result,
|
|
|
|
Manifest **p1, Manifest **p2, ManifestEntry **resultEntry);
|
|
|
|
|
2017-04-20 07:14:03 +03:00
|
|
|
bool next(std::string **path, Manifest **result,
|
|
|
|
Manifest **p1, Manifest **p2);
|
2017-04-20 07:14:03 +03:00
|
|
|
|
2016-09-20 22:42:23 +03:00
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Pops the current Manifest, populating the output values and returning true
|
|
|
|
* if the current Manifest is different from all comparison manifests.
|
|
|
|
*/
|
2017-04-20 07:14:03 +03:00
|
|
|
void popResult(std::string **path, Manifest **result,
|
2017-04-20 07:14:03 +03:00
|
|
|
Manifest **p1, Manifest **p2);
|
2016-09-20 22:42:23 +03:00
|
|
|
|
|
|
|
/** Pushes the given Manifest onto the stacks. If the given Manifest equals
|
|
|
|
* one of the comparison Manifests, the function does nothing.
|
|
|
|
*/
|
|
|
|
bool processDirectory(ManifestEntry *mainEntry);
|
|
|
|
};
|
|
|
|
|
2017-04-20 07:14:03 +03:00
|
|
|
class FinalizeIterator {
|
|
|
|
private:
|
|
|
|
SubtreeIterator _iterator;
|
|
|
|
public:
|
|
|
|
FinalizeIterator(Manifest *mainRoot,
|
2017-04-26 01:44:55 +03:00
|
|
|
const std::vector<const char*> &cmpNodes,
|
2017-04-20 07:14:03 +03:00
|
|
|
const std::vector<Manifest*> &cmpRoots,
|
|
|
|
const ManifestFetcher &fetcher);
|
|
|
|
|
|
|
|
bool next(std::string **path, Manifest **result,
|
|
|
|
Manifest **p1, Manifest **p2);
|
|
|
|
};
|
|
|
|
|
2016-09-06 22:10:35 +03:00
|
|
|
/**
|
|
|
|
* A helper struct representing the state of an iterator recursing over a tree.
|
|
|
|
*/
|
|
|
|
struct fileiter {
|
|
|
|
ManifestFetcher fetcher; // Instance to fetch tree content
|
|
|
|
std::vector<stackframe> frames;
|
|
|
|
std::string path; // The fullpath for the top entry in the stack.
|
2016-09-18 23:44:17 +03:00
|
|
|
bool sorted; // enable mercurial sorting?
|
2016-09-06 22:10:35 +03:00
|
|
|
|
|
|
|
// If provided, the given matcher filters the results by path
|
2017-03-07 22:39:46 +03:00
|
|
|
std::shared_ptr<Matcher> matcher;
|
2016-09-06 22:10:35 +03:00
|
|
|
|
2016-09-18 23:44:17 +03:00
|
|
|
fileiter(treemanifest &tm, bool sorted) :
|
|
|
|
fetcher(tm.fetcher),
|
|
|
|
sorted(sorted) {
|
|
|
|
this->frames.push_back(stackframe(tm.getRootManifest(), this->sorted));
|
2016-09-06 22:10:35 +03:00
|
|
|
this->path.reserve(1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
fileiter(const fileiter &old) :
|
|
|
|
fetcher(old.fetcher),
|
|
|
|
frames(old.frames),
|
|
|
|
path(old.path) {
|
|
|
|
}
|
|
|
|
|
|
|
|
fileiter& operator=(const fileiter &other) {
|
|
|
|
this->fetcher = other.fetcher;
|
|
|
|
this->frames = other.frames;
|
|
|
|
this->path = other.path;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-03-07 22:39:46 +03:00
|
|
|
struct DiffResult {
|
|
|
|
virtual ~DiffResult() {}
|
|
|
|
virtual void add(const std::string &path,
|
|
|
|
const char *beforeNode, const char *beforeFlag,
|
|
|
|
const char *afterNode, const char *afterFlag) = 0;
|
|
|
|
virtual void addclean(const std::string &path) = 0;
|
|
|
|
};
|
|
|
|
|
2016-09-06 22:09:55 +03:00
|
|
|
extern void treemanifest_diffrecurse(
|
|
|
|
Manifest *selfmf,
|
|
|
|
Manifest *othermf,
|
|
|
|
std::string &path,
|
2017-03-07 22:39:46 +03:00
|
|
|
DiffResult &diff,
|
2016-10-15 02:01:12 +03:00
|
|
|
const ManifestFetcher &fetcher,
|
2017-03-12 22:49:18 +03:00
|
|
|
bool clean,
|
|
|
|
Matcher &matcher);
|
2016-09-06 22:09:55 +03:00
|
|
|
|
2016-08-23 01:45:06 +03:00
|
|
|
#endif //REMOTEFILELOG_TREEMANIFEST_H
|