Artifactory AQL delete empty folders
Asked Answered
D

3

7

How do I delete empty folders(folders without any content) by using Artifactory AQL?

I have the current AQL query to find files that are older than 12w and never downloaded, which I will delete by an script.

items.find(
    {
        "repo":{"$eq":"libs-release-local"},
        "stat.downloads":{"$eq":null},
        "created":{"$before" : "12w"},
    }
)

This leaves me with empty folders, how do I specify an AQL query that finds all empty folders?

Daimon answered 18/11, 2016 at 7:21 Comment(0)
P
4

From Artifactory Query Language documentation: if type is not specified in the query, the default type searched for is file.

By adding a type to the query you can control the result type: file, folder or both.

For example:

items.find(
    {
        "repo": {"$eq":"libs-release-local"},
        "stat.downloads": {"$eq":null},
        "created": {"$before" : "12w"},
        "type": {"$eq":"any"}
    }
)
Prelacy answered 22/11, 2016 at 7:47 Comment(1)
This query finds folders which contains pom/artifacts as well. We are using Maven repos in Artifactory and Gradle as the tool to fetch and I guess that gradle never queries for the folders, just the pom and artifacts inside the folders.Daimon
B
1

If you are not married to the idea of using AQL, note that there is an Empty Folder Clean-up plugin by JFrog.

Bernardinabernardine answered 24/4, 2018 at 0:9 Comment(0)
S
0

Even now, nearly 7 years after the question was asked, it seems this is impossible to do using AQL. Mainly because the AQL 'item' entity doesn't support the 'children' field, so you cannot check for folders where the children field is empty.

AQL entity documentation here: https://jfrog.com/help/r/jfrog-rest-apis/aql-entities-and-fields.

So, I solved this using a Python script that calls the the 'storage' REST API. Apologies I cannot post the actual code here, but the abstract approach is as follows:

  1. Make an HTTP "get" request to the Artifactory storage API specifying the parent path in your repository. To specify the root of the repo, just use "/".

  2. Fetch the 'children' field from the result object.

  3. If the 'children' collection exists and is not empty, then iterate through its contents checking whether each child item is a folder.

    • Folder items have a boolean property 'folder' with a value of True.
    • File items do not have this property.
  4. For any child item which is a folder, recursively call steps 1-7, passing a folder URI which is the product of the current folder URI and the child item's own URI (child URI is relative to its parent)

  5. Count the children of the current folder, taking into account that any child folders might have been deleted. I simply call the storage API again for the current folder to get a fresh view of its 'children' collection, but you could also count and pass back up the recursive call chain.

  6. If no child items remain for the current folder, then make an HTTP "delete" for the current folder's repository and URI.

  7. Return to the caller.

If you are ONLY cleaning up empty folders, the above can be simplified. My own implementation is more complex because I'm checking file 'lastUpdated' timestamps against a configurable retention period and optionally deleting files as well, so I keep track of both files and folders as I recurse the folder structure. This way I housekeep old artefacts, and delete any folders that are left empty as I go.

Scurf answered 14/11, 2023 at 17:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.