From 60e4947cc7934f9b62b88b79be433a6c83ef971c Mon Sep 17 00:00:00 2001 From: Matthew Foley Date: Tue, 26 Jul 2011 04:57:09 +0000 Subject: [PATCH] HADOOP-6385. dfs should support -rmdir (was HDFS-639). Contributed by Daryn Sharp. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1150987 13f79535-47bb-0310-9956-ffa450edef68 --- common/CHANGES.txt | 3 + .../org/apache/hadoop/fs/shell/Delete.java | 55 +++++++++++++++++-- .../hadoop/fs/shell/PathExceptions.java | 9 +++ .../core/org/apache/hadoop/cli/testConf.xml | 33 ++++++++++- 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/common/CHANGES.txt b/common/CHANGES.txt index dccc25cb3a..44b80a7c2e 100644 --- a/common/CHANGES.txt +++ b/common/CHANGES.txt @@ -60,6 +60,9 @@ Trunk (unreleased changes) HADOOP-7460. Support pluggable trash policies. (Usman Masoon via suresh) + HADOOP-6385. dfs should support -rmdir (was HDFS-639). (Daryn Sharp + via mattf) + IMPROVEMENTS HADOOP-7042. Updates to test-patch.sh to include failed test names and diff --git a/common/src/java/org/apache/hadoop/fs/shell/Delete.java b/common/src/java/org/apache/hadoop/fs/shell/Delete.java index 5dc849e29b..71bfc9510d 100644 --- a/common/src/java/org/apache/hadoop/fs/shell/Delete.java +++ b/common/src/java/org/apache/hadoop/fs/shell/Delete.java @@ -27,6 +27,8 @@ import org.apache.hadoop.fs.Trash; import org.apache.hadoop.fs.shell.PathExceptions.PathIOException; import org.apache.hadoop.fs.shell.PathExceptions.PathIsDirectoryException; +import org.apache.hadoop.fs.shell.PathExceptions.PathIsNotDirectoryException; +import org.apache.hadoop.fs.shell.PathExceptions.PathIsNotEmptyDirectoryException; /** * Classes that delete paths @@ -34,9 +36,10 @@ @InterfaceAudience.Private @InterfaceStability.Evolving -class Delete extends FsCommand { +class Delete { public static void registerCommands(CommandFactory factory) { factory.addClass(Rm.class, "-rm"); + factory.addClass(Rmdir.class, "-rmdir"); factory.addClass(Rmr.class, "-rmr"); factory.addClass(Expunge.class, "-expunge"); } @@ -44,26 +47,35 @@ public static void registerCommands(CommandFactory factory) { /** remove non-directory paths */ public static class Rm extends FsCommand { public static final String NAME = "rm"; - public static final String USAGE = "[-r|-R] [-skipTrash] ..."; + public static final String USAGE = "[-f] [-r|-R] [-skipTrash] ..."; public static final String DESCRIPTION = "Delete all files that match the specified file pattern.\n" + "Equivalent to the Unix command \"rm \"\n" + "-skipTrash option bypasses trash, if enabled, and immediately\n" + "deletes \n" + + " -f If the file does not exist, do not display a diagnostic\n" + + " message or modify the exit status to reflect an error.\n" + " -[rR] Recursively deletes directories"; private boolean skipTrash = false; private boolean deleteDirs = false; + private boolean ignoreFNF = false; @Override protected void processOptions(LinkedList args) throws IOException { CommandFormat cf = new CommandFormat( - 1, Integer.MAX_VALUE, "r", "R", "skipTrash"); + 1, Integer.MAX_VALUE, "f", "r", "R", "skipTrash"); cf.parse(args); + ignoreFNF = cf.getOpt("f"); deleteDirs = cf.getOpt("r") || cf.getOpt("R"); skipTrash = cf.getOpt("skipTrash"); } - + + @Override + protected void processNonexistentPath(PathData item) throws IOException { + if (!ignoreFNF) super.processNonexistentPath(item); + } + @Override protected void processPath(PathData item) throws IOException { if (item.stat.isDirectory() && !deleteDirs) { @@ -112,7 +124,40 @@ public String getReplacementCommand() { return "rm -r"; } } - + + /** remove only empty directories */ + static class Rmdir extends FsCommand { + public static final String NAME = "rmdir"; + public static final String USAGE = + "[--ignore-fail-on-non-empty] ..."; + public static final String DESCRIPTION = + "Removes the directory entry specified by each directory argument,\n" + + "provided it is empty.\n"; + + private boolean ignoreNonEmpty = false; + + protected void processOptions(LinkedList args) throws IOException { + CommandFormat cf = new CommandFormat( + 1, Integer.MAX_VALUE, "-ignore-fail-on-non-empty"); + cf.parse(args); + ignoreNonEmpty = cf.getOpt("-ignore-fail-on-non-empty"); + } + + @Override + protected void processPath(PathData item) throws IOException { + if (!item.stat.isDirectory()) { + throw new PathIsNotDirectoryException(item.toString()); + } + if (item.fs.listStatus(item.path).length == 0) { + if (!item.fs.delete(item.path, false)) { + throw new PathIOException(item.toString()); + } + } else if (!ignoreNonEmpty) { + throw new PathIsNotEmptyDirectoryException(item.toString()); + } + } + } + /** empty the trash */ static class Expunge extends FsCommand { public static final String NAME = "expunge"; diff --git a/common/src/java/org/apache/hadoop/fs/shell/PathExceptions.java b/common/src/java/org/apache/hadoop/fs/shell/PathExceptions.java index a08ca07cc3..66d2a35e27 100644 --- a/common/src/java/org/apache/hadoop/fs/shell/PathExceptions.java +++ b/common/src/java/org/apache/hadoop/fs/shell/PathExceptions.java @@ -31,6 +31,7 @@ @InterfaceAudience.Private @InterfaceStability.Unstable +@SuppressWarnings("serial") public class PathExceptions { /** EIO */ @@ -165,6 +166,14 @@ public PathIsNotDirectoryException(String path) { } } + /** Generated by rm commands */ + public static class PathIsNotEmptyDirectoryException extends PathExistsException { + /** @param path for the exception */ + public PathIsNotEmptyDirectoryException(String path) { + super(path, "Directory is not empty"); + } + } + /** EACCES */ public static class PathAccessDeniedException extends PathIOException { static final long serialVersionUID = 0L; diff --git a/common/src/test/core/org/apache/hadoop/cli/testConf.xml b/common/src/test/core/org/apache/hadoop/cli/testConf.xml index d8b5785682..e148fffcc1 100644 --- a/common/src/test/core/org/apache/hadoop/cli/testConf.xml +++ b/common/src/test/core/org/apache/hadoop/cli/testConf.xml @@ -283,7 +283,7 @@ RegexpComparator - ^-rm \[-r\|-R\] \[-skipTrash\] <src> \.\.\.:( |\t)*Delete all files that match the specified file pattern.( )* + ^-rm \[-f\] \[-r\|-R\] \[-skipTrash\] <src> \.\.\.:( |\t)*Delete all files that match the specified file pattern.( )* RegexpComparator @@ -297,6 +297,37 @@ RegexpComparator ^( |\t)*deletes <src>( )* + + RegexpComparator + ^\s+-f\s+If the file does not exist, do not display a diagnostic + + + RegexpComparator + ^\s+message or modify the exit status to reflect an error\. + + + RegexpComparator + ^\s+-\[rR\]\s+Recursively deletes directories + + + + + + help: help for rmdir + + -help rmdir + + + + + + RegexpComparator + ^-rmdir \[--ignore-fail-on-non-empty\] <dir> \.\.\.:\s+Removes the directory entry specified by each directory argument, + + + RegexpComparator + \s+provided it is empty. +