从Nexus 3中清除旧版本

12
我使用 Nexus 3,想要删除旧版本。在 Nexus 2 中,有一个名为“从仓库中删除版本”的定时任务,但在 Nexus 3 中好像没有这个任务。
那么如何从 Nexus 3 中删除旧版本呢?
谢谢。

1
如果您想跟进,这似乎是 https://issues.sonatype.org/browse/NEXUS-10821。 - joedragons
7个回答

13

自从Nexus 3发布以来,您可以将Groovy脚本部署到Nexus管理器中。只需创建一个新的执行脚本任务,并使用以下脚本:

import org.sonatype.nexus.repository.storage.StorageFacet;
import org.sonatype.nexus.common.app.GlobalComponentLookupHelper
import org.sonatype.nexus.repository.maintenance.MaintenanceService
import org.sonatype.nexus.repository.storage.ComponentMaintenance
import org.sonatype.nexus.repository.storage.Query;
import org.sonatype.nexus.script.plugin.RepositoryApi
import org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl
import com.google.common.collect.ImmutableList
import org.joda.time.DateTime;
import org.slf4j.Logger

// ----------------------------------------------------
// delete these rows when this script is added to nexus
RepositoryApiImpl repository = null;
Logger log = null;
GlobalComponentLookupHelper container = null;
// ----------------------------------------------------

def retentionDays = 30;
def retentionCount = 10;
def repositoryName = 'maven-releases';
def whitelist = ["org.javaee7.sample/javaee7-simple-sample", "org.javaee7.next/javaee7-another-sample"].toArray();


log.info(":::Cleanup script started!");
MaintenanceService service = container.lookup("org.sonatype.nexus.repository.maintenance.MaintenanceService");
def repo = repository.repositoryManager.get(repositoryName);
def tx = repo.facet(StorageFacet.class).txSupplier().get();
def components = null;
try {
    tx.begin();
    components = tx.browseComponents(tx.findBucket(repo));
}catch(Exception e){
    log.info("Error: "+e);
}finally{
    if(tx!=null)
        tx.close();
}

if(components != null) {
    def retentionDate = DateTime.now().minusDays(retentionDays).dayOfMonth().roundFloorCopy();
    int deletedComponentCount = 0;
    int compCount = 0;
    def listOfComponents = ImmutableList.copyOf(components);
    def previousComp = listOfComponents.head().group() + listOfComponents.head().name();
    listOfComponents.reverseEach{comp ->
        log.info("Processing Component - group: ${comp.group()}, ${comp.name()}, version: ${comp.version()}");
        if(!whitelist.contains(comp.group()+"/"+comp.name())){
            log.info("previous: ${previousComp}");
            if(previousComp.equals(comp.group() + comp.name())) {
                compCount++;
                log.info("ComCount: ${compCount}, ReteCount: ${retentionCount}");
                if (compCount > retentionCount) {
                    log.info("CompDate: ${comp.lastUpdated()} RetDate: ${retentionDate}");
                    if(comp.lastUpdated().isBefore(retentionDate)) {
                        log.info("compDate after retentionDate: ${comp.lastUpdated()} isAfter ${retentionDate}");
                        log.info("deleting ${comp.group()}, ${comp.name()}, version: ${comp.version()}");

                        // ------------------------------------------------
                        // uncomment to delete components and their assets
                        // service.deleteComponent(repo, comp);
                        // ------------------------------------------------

                        log.info("component deleted");
                        deletedComponentCount++;
                    }
                }
            } else {
                compCount = 1;
                previousComp = comp.group() + comp.name();
            }
        }else{
            log.info("Component skipped: ${comp.group()} ${comp.name()}");
        }
    }

    log.info("Deleted Component count: ${deletedComponentCount}");
}

https://github.com/xninjaxelitex/nexus3-cleanup-release-artifact

此脚本将按照顶部指定的参数清理您的nexus存储库。


1
+1这个解决方案是有效的。不要忘记按照脚本中的指示修改代码并添加/删除注释行。 - Lukman
删除API在我们的版本中似乎已经更改。我用以下代码替换了service.deleteComponent:try{ tx = repo.facet(StorageFacet.class).txSupplier().get(); tx.begin(); tx.deleteComponent(comp); }finally{ if(tx!=null){ tx.close(); } } - Daniel Bower
@ninjaxelite,运行这个脚本就足以释放磁盘空间吗?还是需要其他的操作?我使用相同的机制(service.deleteComponent())运行了我的脚本,以删除一个单独的包,这个包似乎已经从nexus中删除了,但我没有注意到任何在nexus上释放的磁盘空间。 - rideronthestorm
如果软件包成功删除,它当然应该释放磁盘空间。 - ninjaxelite
@ninjaxelite 我发现如果使用脚本,排序并不完全正确。版本1.10将出现在版本1.2之前。有没有一种方法可以使用自然排序顺序对它们进行排序?(还考虑例如RC-10、RC-1版本)? - JDC
显示剩余3条评论

7
请参考以下脚本:

https://gist.github.com/emexelem/bcf6b504d81ea9019ad4ab2369006e66,作者是emexelem。


该脚本可作为您工作的基础。
import org.sonatype.nexus.repository.storage.StorageFacet;
import org.sonatype.nexus.repository.storage.Query;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

def fmt = DateTimeFormat.forPattern('yyyy-MM-dd HH:mm:ss');
// Get a repository
def repo = repository.repositoryManager.get('nuget-releases');
// Get a database transaction
def tx = repo.facet(StorageFacet).txSupplier().get();
// Begin the transaction
tx.begin();
// Search assets that havn't been downloaded for more than three months
tx.findAssets(Query.builder().where('last_downloaded <').param(DateTime.now().minusMonths(3).toString(fmt)).build(), [repo]).each { asset ->
  def component = tx.findComponent(asset.componentId());
  // Check if there is newer components of the same name
  def count = tx.countComponents(Query.builder().where('name').eq(component.name()).and('version >').param(component.version()).build(), [repo]);
  if (count > 0) {
    log.info("Delete asset ${asset.name()} as it has not been downloaded since 3 months and has a newer version")
    tx.deleteAsset(asset);
    tx.deleteComponent(component);
  }
}
// End the transaction
tx.commit();

4

我遇到了一个问题,由于我们的发布/构建不断增加,导致磁盘空间不足。因此,我开始尝试创建一个脚本来删除旧的构建版本,最终得到了以下代码:

import org.sonatype.nexus.repository.storage.StorageFacet;
import org.sonatype.nexus.repository.storage.Query;

def repositoryName = 'Integration';
def maxArtifactCount = 20;

// Get a repository
def repo = repository.repositoryManager.get(repositoryName);
// Get a database transaction
def tx = repo.facet(StorageFacet).txSupplier().get();
try {
    // Begin the transaction
    tx.begin();

    def previousComponent = null;
    def uniqueComponents = [];
    tx.findComponents(Query.builder().suffix(' ORDER BY group, name').build(), [repo]).each{component -> 
        if (previousComponent == null || (!component.group().equals(previousComponent.group()) || !component.name().equals(previousComponent.name()))) {
            uniqueComponents.add(component);
        }
        previousComponent = component;
    }

    uniqueComponents.each {uniqueComponent ->
        def componentVersions = tx.findComponents(Query.builder().where('group = ').param(uniqueComponent.group()).and('name = ').param(uniqueComponent.name()).suffix(' ORDER BY last_updated DESC').build(), [repo]);
        log.info(uniqueComponent.group() + ", " + uniqueComponent.name() + " size " + componentVersions.size());
        if (componentVersions.size() > maxArtifactCount) {
            componentVersions.eachWithIndex { component, index ->
                if (index > maxArtifactCount) {
                    log.info("Deleting Component ${component.group()} ${component.name()} ${component.version()}")
                    tx.deleteComponent(component);
                }
            }
        }
    }
} finally {
    // End the transaction
    tx.commit();
}

这个操作通过存储库查找所有组件。然后按最后更新的顺序依次遍历所有版本(我无法按版本号排序,但我认为这应该没问题),最后删除超过maxArtifactCount数量的任何内容。 希望这对你有所帮助 - 如果你发现任何问题,请让我知道。

3

目前我们还没有建立这个定期任务,如果您需要手动删除发布,可以使用UI中的“删除组件”功能。


谢谢您的回答。有没有办法手动删除已发布的组件?我们有很多组件,逐个点击删除按钮非常繁琐。 - vespasien
1
目前还不能通过用户界面以批量方式进行操作。但是,可以使用脚本API编写Groovy脚本来实现这一功能。 - DarthHater
1
这个清除功能变得更加重要,因为在nexus 3中使用blob存储时,我们无法直接从文件系统中清除构件。 我查看了https://books.sonatype.com/nexus-book/3.0/reference/scripting.html和https://github.com/sonatype/nexus-book-examples/tree/nexus-3.x/scripting,但没有找到批量删除发布的脚本的明显方法。您能提供更精确的起点吗? - Maxime Lem
我正在内部提出这个问题,我同意你的看法Maxime。目前还没有起点,但如果你想自己动手做,你需要看一下快照删除任务的工作原理,然后设计一个可以有效完成发布版本删除的东西。我会尽力为你争取更好的解决方案。 - DarthHater
1
我的同事编写了这个脚本来清理旧版本,希望对其他人有用。 - Maxime Lem
显示剩余2条评论

3

虽然旧贴但仍是当前的话题。

从Nexus 2.x升级到Nexus 3.x后,内置功能中保留最新X个版本的功能不幸消失了。当然有一个功能请求: https://issues.sonatype.org/browse/NEXUS-10821

我尝试使用Matt Harrison的脚本(在本帖早些时候看到),但Nexus中的迁移工具将所有last_updated-值重置为迁移日期,很遗憾。

我尝试通过“ ORDER BY version DESC”对版本进行排序,但结果很混乱,在我的情况下版本3.9.03.11.0更新等等,不适用于我的情况。

所以我在脚本中添加了一些辅助列表、更多日志输出(感谢neil201)和由founddrama开发的版本排序器(https://gist.github.com/founddrama/971284) - 然后,我拥有了一个良好的解决方案!

import org.sonatype.nexus.repository.storage.StorageFacet;
import org.sonatype.nexus.repository.storage.Query;

def repositoryName = 'myrepo';
def maxArtifactCount = 42;

log.info("==================================================");
log.info(":::Cleanup script started...");
log.info("==================================================");
log.info(":::Operating on Repository: ${repositoryName}");
log.info("==================================================");

// Get a repository
def repo = repository.repositoryManager.get(repositoryName);
// Get a database transaction
def tx = repo.facet(StorageFacet).txSupplier().get();
try {
    // Begin the transaction
    tx.begin();

    int totalDelCompCount = 0;
    def previousComponent = null;
    def uniqueComponents = [];
    tx.findComponents(Query.builder().suffix(' ORDER BY group, name').build(), [repo]).each{component -> 
        if (previousComponent == null || (!component.group().equals(previousComponent.group()) || !component.name().equals(previousComponent.name()))) {
            uniqueComponents.add(component);
        }
        previousComponent = component;
    }

    uniqueComponents.each {uniqueComponent ->
        def componentVersions = tx.findComponents(Query.builder().where('group = ').param(uniqueComponent.group()).and('name = ').param(uniqueComponent.name()).suffix(' ORDER BY last_updated DESC').build(), [repo]);
        log.info("Processing Component: ${uniqueComponent.group()}, ${uniqueComponent.name()}");

        def foundVersions = [];
        componentVersions.eachWithIndex { component, index ->
          foundVersions.add(component.version());
         }
         log.info("Found Versions: ${foundVersions}")

        // version-sorting by founddrama 
        def versionComparator = { a, b ->
          def VALID_TOKENS = /.-_/
          a = a.tokenize(VALID_TOKENS)
          b = b.tokenize(VALID_TOKENS)
          
          for (i in 0..<Math.max(a.size(), b.size())) {
            if (i == a.size()) {
              return b[i].isInteger() ? -1 : 1
            } else if (i == b.size()) {
              return a[i].isInteger() ? 1 : -1
            }
            
            if (a[i].isInteger() && b[i].isInteger()) {
              int c = (a[i] as int) <=> (b[i] as int)
              if (c != 0) {
                return c
              }
            } else if (a[i].isInteger()) {
              return 1
            } else if (b[i].isInteger()) {
              return -1
            } else {
              int c = a[i] <=> b[i]
              if (c != 0) {
                return c
              }
            }
          }
          
          return 0
        }

        sortedVersions = foundVersions.sort(versionComparator)
        
        log.info("Sorted Versions: ${sortedVersions}")

        removeVersions = sortedVersions.dropRight(maxArtifactCount)
        
        totalDelCompCount = totalDelCompCount + removeVersions.size();
        
        log.info("Remove Versions: ${removeVersions}");
        
        log.info("Component Total Count: ${componentVersions.size()}");

        log.info("Component Remove Count: ${removeVersions.size()}");

        if (componentVersions.size() > maxArtifactCount) {
            componentVersions.eachWithIndex { component, index ->
                if (component.version() in removeVersions) {
                    log.info("Deleting Component: ${component.group()}, ${component.name()} ${component.version()}")
                    // ------------------------------------------------
                    // uncomment to delete components and their assets
                    // tx.deleteComponent(component);
                    // ------------------------------------------------
                }
            }
        }
        log.info("==================================================");
     
    }
    log.info(" *** Total Deleted Component Count: ${totalDelCompCount} *** ");
    log.info("==================================================");

} finally {
    // End the transaction
    tx.commit();
}

你现在可以在Github上复制这个脚本:https://github.com/PhilSwiss/nexus-cleanup

1
尽管这篇文章很旧,但我有类似的要求,但想根据版本号删除旧的工件/发布,因此需要找到一种方法对它们进行排序并仅保留最新的。

这是我提出的基于此处已经给出的一些示例的脚本。

请注意,这是专门用于清理YUM存储库的,但稍作修改后也适用于其他类型的存储库。

import org.sonatype.nexus.repository.storage.StorageFacet;
import org.sonatype.nexus.repository.storage.Query;
import com.google.common.collect.ImmutableList
import org.joda.time.format.DateTimeFormat;
import org.joda.time.DateTime;
import org.slf4j.Logger

///////////////////////////////
def retentionCount = 3;
def repositoryName = 'repo-name';
def whitelist = [].toArray();
///////////////////////////////

log.info("==================================================");
log.info(":::Cleanup script started...");
log.info("==================================================");
log.info(":::Operating on Repository: ${repositoryName}");
log.info("==================================================");

def repo = repository.repositoryManager.get(repositoryName);
def tx = repo.facet(StorageFacet.class).txSupplier().get();
def components = null;

try {
    // Begin the transaction
    tx.begin();
    components = tx.browseComponents(tx.findBucket(repo));

    if(components != null) {
        int compCount = 0;
        int delCompCount = 0;
        int totalDelCompCount = 0;
        def listOfComponents = ImmutableList.copyOf(components);
        def previousComponent = null;
        def uniqueComponents = [];

        ////////////////////////////////////////////////////////
        final Long MAX_NUMBER = 10000L;

        listOfComponents.each { component ->
            if(!whitelist.contains(component.name())) {
                if (previousComponent == null || !component.name().equals(previousComponent.name())) {
                uniqueComponents.add(component);
            }
            previousComponent = component;
        }
    }

    uniqueComponents.each { uniqueComponent ->

        log.info("Starting Processing on Component: ${uniqueComponent.name()}");

        def artifactVersions = [];
        def numberArray = new ArrayList<Long>();

        tx.findComponents(Query.builder().where('name = ').param(uniqueComponent.name()).build(), [repo]).each { component ->
            def artifactVersion = component.version().replaceAll('-', '.');
            artifactVersions.add(artifactVersion);
        }

        log.info("Found Versions: ${artifactVersions}");

        for(ver in artifactVersions) {

            String[] vers = ver.split('\\.');

            Long num = 0;
            for (int i = 0; i < vers.length; ++i) {
                num = num + Long.valueOf(vers[i]) * (long) Math.pow(MAX_NUMBER, vers.length - i - 1);
            }
            numberArray.add(num);
        }

        numberArray = numberArray.sort(); //.reverse();

        //log.info("Sorting the Versions: ${numberArray}");

        def sortedArtifactVersions = [];

        for (num in numberArray) {
            List<Long> parts = new ArrayList<>();

            while (num > 0) {
                parts.add((long) (num % MAX_NUMBER));
                num = Math.floorDiv(num, MAX_NUMBER);
            }
            String artifact = parts.reverse().join('.');
            sortedArtifactVersions.add(artifact);
        }

        log.info("Sorted Versions: ${sortedArtifactVersions}");

        compCount = sortedArtifactVersions.size();

        def toRemoveArtifactVersions = [];

        if (compCount > retentionCount) {
            toRemoveArtifactVersions = sortedArtifactVersions.dropRight(retentionCount);
        }

        delCompCount = toRemoveArtifactVersions.size();

        totalDelCompCount = totalDelCompCount + delCompCount;

        log.info("Remove Versions: ${toRemoveArtifactVersions}");

        log.info("Component Total Count: ${compCount}");

        log.info("Component Remove Count: ${delCompCount}");

        for (ver in toRemoveArtifactVersions) {

            StringBuilder b = new StringBuilder(ver);
            b.replace(ver.lastIndexOf("."), ver.lastIndexOf(".") + 1, "-" );
            ver = b.toString();

            tx.findComponents(Query.builder().where('name = ').param(uniqueComponent.name()).and('version = ').param(ver).build(), [repo]).each { component ->

                log.info("Deleting Component: ${uniqueComponent.name()} ${ver}");

                // ------------------------------------------------
                // uncomment to delete components and their assets
                // tx.deleteComponent(component);
                // ------------------------------------------------
            }
        }
        log.info("==================================================");
    }
    log.info(" *** Total Deleted Component Count: ${totalDelCompCount} *** ");
    log.info("==================================================");
}

// End the transaction
tx.commit();

} catch(Exception e) {
    log.info("Error: "+e);
    tx.rollback();
} finally {
    tx.close();
}

0

我也遇到了这个相当古老的问题,需要在Nexus 3的发布存储库中删除旧的构件。

在从Nexus 2迁移后,所有的LastUpdated字段都被导入时间戳覆盖了,而不是所有其他解决方案都考虑到了这一点。如在存储库浏览的构件详细信息中所示,有用的信息是包含在属性 -> 内容中的last_modified字段。

@ninjaxelite发布的解决方案开始,感谢@Phil Swiss@neil201,我尝试通过考虑资产而不是组件(属性包含在资产中)来找到一种方法。
一个要求是即使保留期已结束,也要保留至少N个发布版本。
我处理提取出的构件的排序,其中myApp-war-2.12.3.war由于字面排序被认为比myApp-war-2.2.3.war更近,使用@founddrama的解决方案解决了这个问题,就像其他帖子中一样。

考虑到以下解决方案提取所有记录并需要大量的内存和时间来对存储库中的所有项目进行排序和检查,每次脚本被调度时都会出现这种情况。我不能保证它能够正确地处理大型存储库(在10分钟内测试了1.5TB)。任何性能上的改进都将不胜感激。
import org.sonatype.nexus.repository.storage.StorageFacet;
import org.sonatype.nexus.common.app.GlobalComponentLookupHelper
import org.sonatype.nexus.repository.maintenance.MaintenanceService
import org.sonatype.nexus.repository.storage.ComponentMaintenance
import org.sonatype.nexus.repository.storage.Query;
import org.sonatype.nexus.script.plugin.RepositoryApi
import org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl
import com.google.common.collect.Lists
import com.google.common.collect.Iterables
import org.joda.time.DateTime
import org.slf4j.Logger

// ----------------------------------------------------
// delete these rows when this script is added to nexus
//RepositoryApiImpl repository = null;
//Logger log = null;
//GlobalComponentLookupHelper container = null;
// ----------------------------------------------------

// ---------------------- CONFIG ------------------------------
// ATTENTION: This script is skilled for maven repos

// 5 Years of RetentionDays
def retentionDays = 1825;
def retentionCount = 3;
def repositoryName = 'Repository-Name';
def whitelist = ["org.javaee7.sample/javaee7-simple-sample", "org.javaee7.next/javaee7-another-sample"].toArray();
// ------------------------------------------------------------


log.info(":::Cleanup script of ${repositoryName} STARTED!");
MaintenanceService service = container.lookup("org.sonatype.nexus.repository.maintenance.MaintenanceService");
def repo = repository.repositoryManager.get(repositoryName);
def tx = repo.facet(StorageFacet.class).txSupplier().get();
def assets = null;
try {
    tx.begin();
    
    //CAREFUL!!  This query extracts all Assets, do filter the search where possible 
    assets = tx.browseAssets(tx.findBucket(repo));
}catch(Exception e){
    log.info("Error: "+e);
}finally{
    if(tx!=null)
        tx.close();
}

if(assets != null) {
    def retentionDate = DateTime.now().minusDays(retentionDays).dayOfMonth().roundFloorCopy();
    int deletedAssetsCount = 0;
    int assetCount = 1;
    
    List<Iterables> listOfAssets = Lists.newArrayList(assets);
    
    //Base Path of each single project, it will be used for retention count (for each project it will not deleted versions at retentionCount amount)
    def assetBasePath = listOfAssets.head().attributes().get('maven2').get('groupId')+"."+listOfAssets.head().attributes().get('maven2').get('artifactId');
    def currentAsset = null;
    def assetFilename = null;
    
    // ----> ######## Asset List Sorting ##########
    // Considering version number in filename, i.e. myApp-war-2.12.3.war is more recent than myApp-war-2.2.3.war
    
    // version-sorting by founddrama 
    def versionComparator = { itemA, itemB ->
      def VALID_TOKENS = /.-_/
      
      def a = itemA.name().tokenize(VALID_TOKENS)
      def b = itemB.name().tokenize(VALID_TOKENS)
      
      for (i in 0..<Math.max(a.size(), b.size())) {
        if (i == a.size()) {
          return b[i].isInteger() ? -1 : 1
        } else if (i == b.size()) {
          return a[i].isInteger() ? 1 : -1
        }
        
        if (a[i].isInteger() && b[i].isInteger()) {
          int c = (a[i] as int) <=> (b[i] as int)
          if (c != 0) {
            return c
          }
        } else if (a[i].isInteger()) {
          return 1
        } else if (b[i].isInteger()) {
          return -1
        } else {
          int c = a[i] <=> b[i]
          if (c != 0) {
            return c
          }
        }
      }
      
      return 0
    }
    
    log.info("Extracted Asset List Sorting ...");
    listOfAssets = listOfAssets.sort(versionComparator);
    log.info("Extracted Asset List Sorted");
    
    // <---- ######## Asset List Sorting ##########

    listOfAssets.reverseEach{asset ->
    
        if (asset.attributes().get('maven2').get('asset_kind').equals("REPOSITORY_METADATA")){
            //The metadata files are skipped by default
            currentAsset = null;
        }else if (
                asset.attributes().get('maven2').get('groupId') != null
            &&  asset.attributes().get('maven2').get('artifactId') != null
        ){
            // By default the asset basePath it will considered as groupId + artifactId maven attributes
            currentAsset = asset.attributes().get('maven2').get('groupId')+"."+asset.attributes().get('maven2').get('artifactId');
            assetFilename = asset.attributes().get('maven2').get('version')+"."+asset.attributes().get('maven2').get('extension');
        }else{
            // Otherwise, for raw files (and i.e. maven-metadata.xml) the same basePath it is decoded from filename
            // Obvious, it can be used this way in each case avoiding previous code, but I consider it as the second chance
            
            // Cut from penultimate occurrence of / to the end, then replace / with .
            currentAsset = asset.name().replaceAll("(.*)/([^/]+)/([^/]+)", '$1').replaceAll("/", ".");
            assetFilename = asset.name().replaceAll("(.*)/([^/]+)", '$2');
        }
        
        if (currentAsset != null && !whitelist.contains(currentAsset)){
            log.info("Processing Asset : ${currentAsset}, filename: ${assetFilename}");
            log.info("AssetBasePath: ${assetBasePath}");
                
            if(assetBasePath.equals(currentAsset)) {
                log.info("AssetCount: ${assetCount}, Retention: ${retentionCount}");
                if (assetCount > retentionCount) {
                    def lastModifiedDate = asset.attributes().get('content').get('last_modified');
                    DateTime lastModifiedDateTime = lastModifiedDate==null?null:new DateTime(lastModifiedDate);
                    
                    log.debug("AssetLastModified: ${lastModifiedDateTime} - RetentionDate: ${retentionDate}");
                    
                    if (retentionDate.isAfter(lastModifiedDateTime)) {
                        log.info("AssetLastModified ${lastModifiedDateTime} isOldestThan than RetentionDate ${retentionDate}");
                        log.info("Deleting: ${currentAsset}, filename: ${assetFilename}");

                        // ------------------------------------------------
                        // uncomment to delete assets
                        // service.deleteAsset(repo, asset);
                        // ------------------------------------------------

                        log.info("Asset DELETED");
                        deletedAssetsCount++;
                    }
                }
                assetCount++;
            } else {
                assetCount = 1;
                assetBasePath = currentAsset;
            }
        }else{
            log.info("Asset skipped due to whitelisted or Format not supported: ${asset.name()}");
        }
    }

    log.info("TASK END - TOTAL Deleted Asset count: ${deletedAssetsCount}");
}

这个解决方案适用于Maven仓库,但是经过一些修改,我希望它可以对所有类型的仓库有用。
请记得安排“压缩Blob存储”任务,以便在删除构件后释放磁盘空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接