-
-
Notifications
You must be signed in to change notification settings - Fork 188
added optional 'prune' param to file:sync(...) #3084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
aafe3f7
c8f7943
99ebbce
92daf66
5bba21a
154fd86
8259f45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
| import java.nio.file.Path; | ||
| import java.nio.file.StandardCopyOption; | ||
| import java.nio.file.attribute.FileTime; | ||
| import java.net.URISyntaxException; | ||
| import java.util.*; | ||
|
|
||
| import javax.xml.XMLConstants; | ||
|
|
@@ -40,6 +41,7 @@ | |
| import org.exist.xquery.XPathException; | ||
| import org.exist.xquery.XQueryContext; | ||
| import org.exist.xquery.value.DateTimeValue; | ||
| import org.exist.xquery.value.BooleanValue; | ||
| import org.exist.xquery.value.FunctionParameterSequenceType; | ||
| import org.exist.xquery.value.FunctionReturnSequenceType; | ||
| import org.exist.xquery.value.Sequence; | ||
|
|
@@ -64,7 +66,10 @@ public class Sync extends BasicFunction { | |
| Cardinality.EXACTLY_ONE, "The full path or URI to the directory"), | ||
| new FunctionParameterSequenceType("dateTime", Type.DATE_TIME, | ||
| Cardinality.ZERO_OR_ONE, | ||
| "Optional: only resources modified after the given date/time will be synchronized.") | ||
| "Optional: only resources modified after the given date/time will be synchronized."), | ||
| new FunctionParameterSequenceType("prune", Type.BOOLEAN, | ||
| Cardinality.ZERO_OR_ONE, | ||
| "Optional: delete any file/dir that does not correspond to a doc/collection currently in the DB.") | ||
| }, | ||
| new FunctionReturnSequenceType(Type.BOOLEAN, Cardinality.EXACTLY_ONE, "true if successful, false otherwise") | ||
| ); | ||
|
|
@@ -88,15 +93,21 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro | |
| } | ||
|
|
||
| final String collectionPath = args[0].getStringValue(); | ||
|
|
||
| final String target = args[1].getStringValue(); | ||
| Path targetDir = FileModuleHelper.getFile(target); | ||
sten1ee marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Date startDate = null; | ||
| if (args[2].hasOne()) { | ||
| DateTimeValue dtv = (DateTimeValue) args[2].itemAt(0); | ||
| final DateTimeValue dtv = (DateTimeValue) args[2].itemAt(0); | ||
| startDate = dtv.getDate(); | ||
| } | ||
|
|
||
| final String target = args[1].getStringValue(); | ||
| Path targetDir = FileModuleHelper.getFile(target); | ||
|
|
||
|
|
||
| boolean prune = false; | ||
| if (args[3].hasOne()) { | ||
| final BooleanValue bv = (BooleanValue) args[3].itemAt(0); | ||
| prune = bv.getValue(); | ||
| } | ||
|
|
||
| context.pushDocumentContext(); | ||
| final MemTreeBuilder output = context.getDocumentBuilder(); | ||
|
|
@@ -111,7 +122,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro | |
| output.addAttribute(new QName("collection", FileModule.NAMESPACE_URI), collectionPath); | ||
| output.addAttribute(new QName("dir", FileModule.NAMESPACE_URI), targetDir.toAbsolutePath().toString()); | ||
|
|
||
| saveCollection(XmldbURI.create(collectionPath), targetDir, startDate, output); | ||
| saveCollection(XmldbURI.create(collectionPath), targetDir, startDate, prune, output); | ||
|
|
||
| output.endElement(); | ||
| output.endDocument(); | ||
|
|
@@ -123,7 +134,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro | |
| return output.getDocument(); | ||
| } | ||
|
|
||
| private void saveCollection(final XmldbURI collectionPath, Path targetDir, final Date startDate, final MemTreeBuilder output) throws PermissionDeniedException, LockException { | ||
| private void saveCollection(final XmldbURI collectionPath, Path targetDir, final Date startDate, final boolean prune, final MemTreeBuilder output) throws PermissionDeniedException, LockException { | ||
| try { | ||
| targetDir = Files.createDirectories(targetDir); | ||
| } catch(final IOException ioe) { | ||
|
|
@@ -143,6 +154,9 @@ private void saveCollection(final XmldbURI collectionPath, Path targetDir, final | |
| reportError(output, "Collection not found: " + collectionPath); | ||
| return; | ||
| } | ||
| if (prune) { | ||
| pruneCollectionEntries(collection, targetDir, output); | ||
| } | ||
| for (final Iterator<DocumentImpl> i = collection.iterator(context.getBroker()); i.hasNext(); ) { | ||
| DocumentImpl doc = i.next(); | ||
| if (startDate == null || doc.getMetadata().getLastModified() > startDate.getTime()) { | ||
|
||
|
|
@@ -162,7 +176,7 @@ private void saveCollection(final XmldbURI collectionPath, Path targetDir, final | |
|
|
||
| for (final XmldbURI childURI : subcollections) { | ||
| final Path childDir = targetDir.resolve(childURI.lastSegment().toString()); | ||
| saveCollection(collectionPath.append(childURI), childDir, startDate, output); | ||
| saveCollection(collectionPath.append(childURI), childDir, startDate, prune, output); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -172,6 +186,26 @@ private void reportError(final MemTreeBuilder output,final String msg) { | |
| output.endElement(); | ||
| } | ||
|
|
||
| private void pruneCollectionEntries(final Collection collection, final Path targetDir, final MemTreeBuilder output) { | ||
| try { | ||
| Files.walk(targetDir, 1).forEach(path -> { | ||
| try { | ||
| final String fname = path.getFileName().toString(); | ||
| final XmldbURI dbname = XmldbURI.xmldbUriFor(fname); | ||
| if (!collection.hasDocument(context.getBroker(), dbname) | ||
| && !collection.hasChildCollection(context.getBroker(), dbname)) { | ||
| Files.deleteIfExists(path); | ||
| } | ||
| } catch (IOException | URISyntaxException | ||
| | PermissionDeniedException | LockException e) { | ||
| reportError(output, e.getMessage()); | ||
| } | ||
| }); | ||
| } catch (IOException e) { | ||
| reportError(output, e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| private void saveXML(final Path targetDir, final DocumentImpl doc, final MemTreeBuilder output) { | ||
| Path targetFile = targetDir.resolve(doc.getFileURI().toASCIIString()); | ||
| final SAXSerializer sax = (SAXSerializer)SerializerPool.getInstance().borrowObject( SAXSerializer.class ); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Cardinality for this should be EXACTLY_ONE. It doesn't really make sense for this to be optional as it is a boolean value.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made it "optional" with the single purpose that the API remains backward compatible.
Old style invocations of file:sync(...) will still work.
If the
pruneparam is made non-optional, then:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not backwards compatible. There is no polymorphism in XQuery. You have to keep the original function signature, and then define additional function signatures with additional arities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, wait, wait.
Then (in order not to break existing code) this extended 'prune' functionality has to come together with a new function, e.g.
file:sync_ex(...)orfile:sync_prune(...)or something.Is it not so?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need a new named function as they are on different arities. But you have to design two signatures, the original signature, and the new signature which has an additional argument. The new signature should then be added to the
FileModule.java