forked from mirrors/gecko-dev
		
	Bug 1745352 - Add depth param to PathUtils.getParent to get aribtrary ancestors r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D133842
This commit is contained in:
		
							parent
							
								
									a718b52a24
								
							
						
					
					
						commit
						0d04c7d7a6
					
				
					 4 changed files with 82 additions and 8 deletions
				
			
		|  | @ -20,17 +20,19 @@ namespace PathUtils { | ||||||
|   DOMString filename(DOMString path); |   DOMString filename(DOMString path); | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Return the parent directory name of the given path. |    * Return an ancestor directory of the given path. | ||||||
|    * |    * | ||||||
|    * @param path An absolute path. |    * @param path An absolute path. | ||||||
|  |    * @param depth The number of ancestors to remove, defaulting to 1 (i.e., the | ||||||
|  |    *              parent). | ||||||
|    * |    * | ||||||
|    * @return The parent directory. |    * @return The ancestor directory. | ||||||
|    * |    * | ||||||
|    *         If the path provided is a root path (e.g., `C:` on Windows or `/` |    *         If the path provided is a root path (e.g., `C:` on Windows or `/` | ||||||
|    *         on *NIX), then null is returned. |    *         on *NIX), then null is returned. | ||||||
|    */ |    */ | ||||||
|   [Throws] |   [Throws] | ||||||
|   DOMString? parent(DOMString path); |   DOMString? parent(DOMString path, optional long depth = 1); | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Join the given components into a full path. |    * Join the given components into a full path. | ||||||
|  |  | ||||||
|  | @ -142,7 +142,8 @@ void PathUtils::Filename(const GlobalObject&, const nsAString& aPath, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PathUtils::Parent(const GlobalObject&, const nsAString& aPath, | void PathUtils::Parent(const GlobalObject&, const nsAString& aPath, | ||||||
|                        nsString& aResult, ErrorResult& aErr) { |                        const int32_t aDepth, nsString& aResult, | ||||||
|  |                        ErrorResult& aErr) { | ||||||
|   if (aPath.IsEmpty()) { |   if (aPath.IsEmpty()) { | ||||||
|     aErr.ThrowNotAllowedError(ERROR_EMPTY_PATH); |     aErr.ThrowNotAllowedError(ERROR_EMPTY_PATH); | ||||||
|     return; |     return; | ||||||
|  | @ -154,12 +155,20 @@ void PathUtils::Parent(const GlobalObject&, const nsAString& aPath, | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   nsCOMPtr<nsIFile> parent; |   if (aDepth <= 0) { | ||||||
|   if (nsresult rv = path->GetParent(getter_AddRefs(parent)); NS_FAILED(rv)) { |     aErr.ThrowNotSupportedError("A depth of at least 1 is required"); | ||||||
|     ThrowError(aErr, rv, ERROR_GET_PARENT); |  | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   nsCOMPtr<nsIFile> parent; | ||||||
|  |   for (int32_t i = 0; path && i < aDepth; i++) { | ||||||
|  |     if (nsresult rv = path->GetParent(getter_AddRefs(parent)); NS_FAILED(rv)) { | ||||||
|  |       ThrowError(aErr, rv, ERROR_GET_PARENT); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     path = parent; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   if (parent) { |   if (parent) { | ||||||
|     MOZ_ALWAYS_SUCCEEDS(parent->GetPath(aResult)); |     MOZ_ALWAYS_SUCCEEDS(parent->GetPath(aResult)); | ||||||
|   } else { |   } else { | ||||||
|  |  | ||||||
|  | @ -41,7 +41,8 @@ class PathUtils final { | ||||||
|                        nsString& aResult, ErrorResult& aErr); |                        nsString& aResult, ErrorResult& aErr); | ||||||
| 
 | 
 | ||||||
|   static void Parent(const GlobalObject&, const nsAString& aPath, |   static void Parent(const GlobalObject&, const nsAString& aPath, | ||||||
|                      nsString& aResult, ErrorResult& aErr); |                      const int32_t aDepth, nsString& aResult, | ||||||
|  |                      ErrorResult& aErr); | ||||||
| 
 | 
 | ||||||
|   static void Join(const GlobalObject&, const Sequence<nsString>& aComponents, |   static void Join(const GlobalObject&, const Sequence<nsString>& aComponents, | ||||||
|                    nsString& aResult, ErrorResult& aErr); |                    nsString& aResult, ErrorResult& aErr); | ||||||
|  |  | ||||||
|  | @ -119,6 +119,37 @@ | ||||||
|         "\\\\server", |         "\\\\server", | ||||||
|         "PathUtils.parent() with a UNC server path and child component" |         "PathUtils.parent() with a UNC server path and child component" | ||||||
|       ); |       ); | ||||||
|  | 
 | ||||||
|  |       Assert.throws( | ||||||
|  |         () => PathUtils.parent("C:", -1), | ||||||
|  |         /^NotSupportedError: PathUtils.parent: A depth of at least 1 is required/, | ||||||
|  |         "PathUtils.parent() with a negative depth throws" | ||||||
|  |       ); | ||||||
|  |       Assert.throws( | ||||||
|  |         () => PathUtils.parent("C:", 0), | ||||||
|  |         /^NotSupportedError: PathUtils.parent: A depth of at least 1 is required/, | ||||||
|  |         "PathUtils.parent() with a zero depth throws" | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       { | ||||||
|  |         const path = "C:\\Users\\User\\AppData\\Local\\Mozilla\\Firefox\\Profiles\\foo.default"; | ||||||
|  | 
 | ||||||
|  |         const expected = [ | ||||||
|  |           "C:\\Users\\User\\AppData\\Local\\Mozilla\\Firefox\\Profiles", | ||||||
|  |           "C:\\Users\\User\\AppData\\Local\\Mozilla\\Firefox", | ||||||
|  |           "C:\\Users\\User\\AppData\\Local\\Mozilla", | ||||||
|  |           "C:\\Users\\User\\AppData\\Local", | ||||||
|  |           "C:\\Users\\User\\AppData", | ||||||
|  |           "C:\\Users\\User", | ||||||
|  |           "C:\\Users", | ||||||
|  |           "C:", | ||||||
|  |           null, | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         for (const [i, parent] of expected.entries()) { | ||||||
|  |           is(PathUtils.parent(path, i + 1), parent, `PathUtils.parent() with depth=${i + 1}`) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } else { |     } else { | ||||||
|       is( |       is( | ||||||
|         PathUtils.parent("/"), |         PathUtils.parent("/"), | ||||||
|  | @ -135,6 +166,37 @@ | ||||||
|         "/var", |         "/var", | ||||||
|         "PathUtils.parent() with a 3 component path" |         "PathUtils.parent() with a 3 component path" | ||||||
|       ); |       ); | ||||||
|  | 
 | ||||||
|  |       Assert.throws( | ||||||
|  |         () => PathUtils.parent("/", -1), | ||||||
|  |         /^NotSupportedError: PathUtils.parent: A depth of at least 1 is required/, | ||||||
|  |         "PathUtils.parent() with a negative depth throws" | ||||||
|  |       ); | ||||||
|  |       Assert.throws( | ||||||
|  |         () => PathUtils.parent("/", 0), | ||||||
|  |         /^NotSupportedError: PathUtils.parent: A depth of at least 1 is required/, | ||||||
|  |         "PathUtils.parent() with a zero depth throws" | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       { | ||||||
|  |         const path = "/home/user/.mozilla/firefox/foo.default"; | ||||||
|  |         const expected = [ | ||||||
|  |           "/home/user/.mozilla/firefox", | ||||||
|  |           "/home/user/.mozilla", | ||||||
|  |           "/home/user/", | ||||||
|  |           "/home", | ||||||
|  |           "/", | ||||||
|  |           null, | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         for (const [i, parent] of expected.entries()) { | ||||||
|  |           is( | ||||||
|  |             PathUtils.parent(path, i + 1), | ||||||
|  |             parent, | ||||||
|  |             `PathUtils.parent() with depth=${i + 1}` | ||||||
|  |           ); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Barret Rennie
						Barret Rennie