UNPKG

3.61 kBJavaScriptView Raw
1/*
2 * Copyright 2018 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12
13/* eslint-disable no-underscore-dangle */
14
15'use strict';
16
17const crypto = require('crypto');
18const path = require('path');
19
20const fse = require('fs-extra');
21
22/**
23 * Calculates the id (sha1) of a Git Blob.
24 *
25 * @param {string|Buffer} data blob data
26 */
27function calculateBlobSha1(data) {
28 return crypto.createHash('sha1').update(`blob ${data.length}\0`).update(data).digest('hex');
29}
30
31/**
32 * Generates a random name.
33 *
34 * @param {Number} len
35 */
36function randomFileOrFolderName(len = 32) {
37 if (Number.isFinite(len)) {
38 return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len);
39 }
40 throw new Error(`illegal argument: ${len}`);
41}
42
43/**
44 * Resolves the file system path of the specified repository.
45 *
46 * @param {object} options configuration hash
47 * @param {string} owner github org or user
48 * @param {string} repo repository name
49 */
50function resolveRepositoryPath(options, owner, repo) {
51 let repPath = path.resolve(options.repoRoot, owner, repo);
52
53 if (options.virtualRepos[owner] && options.virtualRepos[owner][repo]) {
54 repPath = path.resolve(options.virtualRepos[owner][repo].path);
55 }
56 return repPath;
57}
58
59module.exports._caseInsensitiveFS = undefined;
60
61/**
62 * Returns true if the file system where the current executable was
63 * started from is case-insensitive, otherwise returns false.
64 */
65async function isCaseInsensitiveFS() {
66 if (typeof module.exports._caseInsensitiveFS === 'undefined') {
67 let lcStat;
68 let ucStat;
69 try {
70 lcStat = await fse.stat(process.execPath.toLowerCase());
71 } catch (err) {
72 lcStat = false;
73 }
74 try {
75 ucStat = await fse.stat(process.execPath.toUpperCase());
76 } catch (err) {
77 ucStat = false;
78 }
79 if (lcStat && ucStat) {
80 module.exports._caseInsensitiveFS = lcStat.dev === ucStat.dev && lcStat.ino === ucStat.ino;
81 } else {
82 module.exports._caseInsensitiveFS = false;
83 }
84 }
85 return module.exports._caseInsensitiveFS;
86}
87
88/**
89 * Test whether or not a file system entry exists at `pathToTest` with the same case as specified.
90 *
91 * @param {string} parentDir parent directory where `pathToTest` is rooted
92 * @param {string} pathToTest relative path with segements separated by `/`
93 */
94async function pathExists(parentDir, pathToTest) {
95 if (!await isCaseInsensitiveFS()) {
96 return fse.pathExists(path.join(parentDir, pathToTest));
97 }
98
99 let parent = parentDir;
100
101 // pathToTest is using `/` for separating segments
102 const names = pathToTest.split('/').filter((el) => el !== '');
103 for (let i = 0; i < names.length; i += 1) {
104 const nm = names[i];
105 try {
106 // eslint-disable-next-line no-await-in-loop
107 if (!(await fse.readdir(parent)).filter((el) => el === nm).length) {
108 return false;
109 }
110 } catch (err) {
111 return false;
112 }
113 parent = path.join(parent, nm);
114 }
115 return true;
116}
117
118module.exports = {
119 resolveRepositoryPath,
120 calculateBlobSha1,
121 randomFileOrFolderName,
122 isCaseInsensitiveFS,
123 pathExists,
124};