mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Fixes to apply recursive (#7714)
* Fix apply recursive Promise.all to correctly await promises and fix apply to not apply defaults to child files. * PR comments
This commit is contained in:
@@ -202,8 +202,8 @@ export class AclEntry {
|
||||
* user::r-x
|
||||
* default:group::r--
|
||||
*/
|
||||
toAclStrings(): string[] {
|
||||
return Array.from(this.permissions.entries()).map((entry: [AclEntryScope, AclEntryPermission]) => {
|
||||
toAclStrings(includeDefaults: boolean = true): string[] {
|
||||
return Array.from(this.permissions.entries()).filter((entry: [AclEntryScope, AclEntryPermission]) => includeDefaults || entry[0] !== AclEntryScope.default).map((entry: [AclEntryScope, AclEntryPermission]) => {
|
||||
return `${entry[0] === AclEntryScope.default ? 'default:' : ''}${getAclEntryType(this.type)}:${this.name}:${entry[1].toString()}`;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,12 +3,34 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export enum HdfsFileType {
|
||||
import { FileType } from '../objectExplorerNodeProvider/fileSources';
|
||||
|
||||
export const enum HdfsFileType {
|
||||
File = 'File',
|
||||
Directory = 'Directory',
|
||||
Symlink = 'Symlink'
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a @see HdfsFileType to its corresponding @see FileType. Will return undefined if
|
||||
* passed in type is undefined.
|
||||
* @param hdfsFileType The HdfsFileType to map from
|
||||
*/
|
||||
export function hdfsFileTypeToFileType(hdfsFileType: HdfsFileType | undefined): FileType | undefined {
|
||||
switch (hdfsFileType) {
|
||||
case HdfsFileType.Directory:
|
||||
return FileType.Directory;
|
||||
case HdfsFileType.File:
|
||||
return FileType.File;
|
||||
case HdfsFileType.Symlink:
|
||||
return FileType.Symlink;
|
||||
case undefined:
|
||||
return undefined;
|
||||
default:
|
||||
throw new Error(`Unexpected file type ${hdfsFileType}`);
|
||||
}
|
||||
}
|
||||
|
||||
export class FileStatus {
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { IFileSource } from '../objectExplorerNodeProvider/fileSources';
|
||||
import { IFileSource, FileType } from '../objectExplorerNodeProvider/fileSources';
|
||||
import { PermissionStatus, AclEntry, AclEntryScope, AclType, AclEntryPermission } from './aclEntry';
|
||||
import { FileStatus } from './fileStatus';
|
||||
import { FileStatus, hdfsFileTypeToFileType } from './fileStatus';
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
@@ -84,7 +84,7 @@ export class HdfsModel {
|
||||
* @param recursive Whether to apply the changes recursively (to all sub-folders and files)
|
||||
*/
|
||||
public async apply(recursive: boolean = false): Promise<void> {
|
||||
await this.applyAclChanges(this.path);
|
||||
await this.applyAclChanges(this.path, hdfsFileTypeToFileType(this.fileStatus ? this.fileStatus.type : undefined));
|
||||
if (recursive) {
|
||||
azdata.tasks.startBackgroundOperation(
|
||||
{
|
||||
@@ -112,10 +112,9 @@ export class HdfsModel {
|
||||
const files = await this.fileSource.enumerateFiles(path, true);
|
||||
// Apply changes to all children of this path and then recursively apply to children of any directories
|
||||
await Promise.all(
|
||||
[
|
||||
files.map(file => this.applyAclChanges(file.path)),
|
||||
files.filter(f => f.isDirectory).map(d => this.applyToChildrenRecursive(op, d.path))
|
||||
]);
|
||||
files.map(file => this.applyAclChanges(file.path, file.fileType)).concat(
|
||||
files.filter(f => f.fileType === FileType.Directory).map(d => this.applyToChildrenRecursive(op, d.path)))
|
||||
);
|
||||
} catch (error) {
|
||||
const errMsg = localize('mssql.recursivePermissionOpError', "Error applying permission changes: {0}", (error instanceof Error ? error.message : error));
|
||||
vscode.window.showErrorMessage(errMsg);
|
||||
@@ -127,7 +126,7 @@ export class HdfsModel {
|
||||
* Applies the current set of Permissions/ACLs to the specified path
|
||||
* @param path The path to apply the changes to
|
||||
*/
|
||||
private async applyAclChanges(path: string): Promise<any> {
|
||||
private async applyAclChanges(path: string, fileType: FileType | undefined): Promise<any> {
|
||||
// HDFS won't remove existing default ACLs even if you call setAcl with no default ACLs specified. You
|
||||
// need to call removeDefaultAcl specifically to remove them.
|
||||
if (!this.permissionStatus.owner.getPermission(AclEntryScope.default) &&
|
||||
@@ -136,7 +135,7 @@ export class HdfsModel {
|
||||
await this.fileSource.removeDefaultAcl(path);
|
||||
}
|
||||
return Promise.all([
|
||||
this.fileSource.setAcl(path, this.permissionStatus.owner, this.permissionStatus.group, this.permissionStatus.other, this.permissionStatus.aclEntries),
|
||||
this.fileSource.setAcl(path, fileType, this.permissionStatus),
|
||||
this.fileSource.setPermission(path, this.permissionStatus)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Cookie } from 'tough-cookie';
|
||||
import * as through from 'through2';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as auth from '../util/auth';
|
||||
import { IHdfsOptions, IRequestParams } from '../objectExplorerNodeProvider/fileSources';
|
||||
import { IHdfsOptions, IRequestParams, FileType } from '../objectExplorerNodeProvider/fileSources';
|
||||
import { PermissionStatus, AclEntry, parseAclList, PermissionType, parseAclPermissionFromOctal, AclEntryScope, AclType } from './aclEntry';
|
||||
import { Mount } from './mount';
|
||||
import { everyoneName, ownerPostfix, owningGroupPostfix } from '../localizedConstants';
|
||||
@@ -509,20 +509,15 @@ export class WebHDFS {
|
||||
/**
|
||||
* Set ACL for the given path. The owner, group and other fields are required - other entries are optional.
|
||||
* @param path The path to the file/folder to set the ACL on
|
||||
* @param ownerEntry The entry corresponding to the path owner
|
||||
* @param groupEntry The entry corresponding to the path owning group
|
||||
* @param otherEntry The entry corresponding to default permissions for all other users
|
||||
* @param aclEntries The optional additional ACL entries to set
|
||||
* @param fileType The type of file we're setting to determine if defaults should be applied. Use undefined if type is unknown
|
||||
* @param ownerEntry The status containing the permissions to set
|
||||
* @param callback Callback to handle the response
|
||||
*/
|
||||
public setAcl(path: string, ownerEntry: AclEntry, groupEntry: AclEntry, otherEntry: AclEntry, aclEntries: AclEntry[], callback: (error: HdfsError) => void): void {
|
||||
public setAcl(path: string, fileType: FileType | undefined, permissionStatus: PermissionStatus, callback: (error: HdfsError) => void): void {
|
||||
this.checkArgDefined('path', path);
|
||||
this.checkArgDefined('ownerEntry', ownerEntry);
|
||||
this.checkArgDefined('groupEntry', groupEntry);
|
||||
this.checkArgDefined('otherEntry', otherEntry);
|
||||
this.checkArgDefined('aclEntries', aclEntries);
|
||||
const concatEntries = [ownerEntry, groupEntry, otherEntry].concat(aclEntries);
|
||||
const aclSpec = concatEntries.reduce((acc, entry) => acc.concat(entry.toAclStrings()), []).join(',');
|
||||
this.checkArgDefined('permissionStatus', permissionStatus);
|
||||
const concatEntries = [permissionStatus.owner, permissionStatus.group, permissionStatus.other].concat(permissionStatus.aclEntries);
|
||||
const aclSpec = concatEntries.reduce((acc, entry: AclEntry) => acc.concat(entry.toAclStrings(fileType !== FileType.File)), []).join(',');
|
||||
let endpoint = this.getOperationEndpoint('setacl', path, { aclspec: aclSpec });
|
||||
this.sendRequest('PUT', endpoint, undefined, (error) => {
|
||||
return callback && callback(error);
|
||||
|
||||
Reference in New Issue
Block a user