• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { existsSync, readFileSync, writeFileSync } from 'fs';
17import { readJsonSync } from 'fs-extra';
18import type { IOptions } from '../configs/IOptions';
19import { fileExtensions } from '../common/type';
20import type { PathAndExtension } from '../common/type';
21import fs from 'fs';
22
23export class FileUtils {
24  /**
25   * Read file and return content
26   *
27   * @param filePath file path
28   */
29  public static readFile(filePath: string): string | undefined {
30    if (!existsSync(filePath)) {
31      console.error(`File <${this.getFileName(filePath)} is not found.>`);
32      return undefined;
33    }
34    return readFileSync(filePath, 'utf-8');
35  }
36
37  /**
38   * Read file and convert to json object.
39   *
40   * @param filePath file path
41   */
42  public static readFileAsJson(filePath: string): IOptions | undefined {
43    if (!existsSync(filePath)) {
44      console.error(`File <${this.getFileName(filePath)} is not found.>`);
45      return undefined;
46    }
47
48    try {
49      return readJsonSync(filePath);
50    } catch (e) {
51      console.error('json file read error: ' + filePath);
52      return undefined;
53    }
54  }
55
56  /**
57   * Get File Name
58   *
59   * @param filePath file path
60   */
61  public static getFileName(filePath: string): string | undefined {
62    if (!filePath) {
63      return undefined;
64    }
65
66    const lastSepIndex: number = filePath.lastIndexOf('/');
67    if (lastSepIndex >= 0) {
68      return filePath.slice(lastSepIndex + 1);
69    }
70
71    return filePath.slice(filePath.lastIndexOf('\\') + 1);
72  }
73
74  /**
75   * Get suffix of a file.
76   *
77   * @param filePath file path
78   */
79  public static getFileExtension(filePath: string): string | undefined {
80    if (!filePath || !filePath.includes('.')) {
81      return undefined;
82    }
83
84    // get file name
85    let fileName: string = this.getFileName(filePath);
86    if (!fileName.includes('.')) {
87      return undefined;
88    }
89
90    return fileName.slice(fileName.lastIndexOf('.') + 1);
91  }
92
93  public static writeFile(filePath: string, content: string): void {
94    writeFileSync(filePath, content);
95  }
96
97  /**
98   * get prefix of directory
99   * @param dirPath
100   */
101  public static getPrefix(dirPath: string): string | undefined {
102    if (!dirPath || (!dirPath.includes('/') && !dirPath.includes('\\'))) {
103      return undefined;
104    }
105
106    const sepIndex: number = dirPath.lastIndexOf('/');
107    if (sepIndex >= 0) {
108      return dirPath.slice(0, sepIndex + 1);
109    }
110
111    return dirPath.slice(0, dirPath.lastIndexOf('\\') + 1);
112  }
113
114  public static getPathWithoutPrefix(filePath: string, prefix: string): string | undefined {
115    if (!filePath.startsWith(prefix)) {
116      return filePath;
117    }
118
119    return filePath.slice(prefix.length);
120  }
121
122  public static splitFilePath(filePath: string): string[] {
123    if (!filePath.includes('\\') && !filePath.includes('\/')) {
124      return [filePath];
125    }
126    const directories = filePath.split(/[\/\\]/);
127    const output: string[] = [];
128    /* path: /foo//bar; the target output is ['', 'foo', '', 'bar'].
129     * if the first empty string is deleted, the path joining of the Linux platform folder is 'foo/bar'.
130     */
131    if (directories.length > 0 && directories[0] === '') {
132      output.push('');
133    }
134
135    output.push(...(directories.filter(part => part !== '')));
136    return directories;
137  }
138
139  static relativePathBegins: string[] = ['./', '../', '.\\', '..\\'];
140  public static isRelativePath(filePath: string): boolean {
141    for (const bebin of this.relativePathBegins) {
142      if (filePath.startsWith(bebin)) {
143        return true;
144      }
145    }
146    return false;
147  }
148
149  public static getFileSuffix(filePath: string): PathAndExtension {
150    for (let ext of fileExtensions) {
151      if (filePath.endsWith(ext)) {
152        const filePathWithoutSuffix: string = filePath.replace(new RegExp(`${ext}$`), '');
153        return { path: filePathWithoutSuffix, ext: ext };
154      }
155    }
156    return { path: filePath, ext: '' };
157  }
158
159  public static isReadableFile(filePath: string): boolean {
160    try {
161      fs.accessSync(filePath, fs.constants.R_OK);
162    } catch (err) {
163      return false;
164    }
165    return true;
166  }
167}
168