PplatonovvladislavSome codecheck fixes
eecbf305创建于 3月24日历史提交
/*
 * Copyright (c) 2026 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Minimal sync glob expander: * (one segment) and ** (recursive).
 * No external dependencies; matches patterns used in rimraf scripts.
 */

import fs from 'node:fs';
import path from 'node:path';

/**
 * Convert a single path segment pattern to a RegExp.
 * * matches any characters except path separator.
 */
function segmentRegex(seg) {
  const escaped = seg.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^/]*');
  return new RegExp(`^${escaped}$`);
}

/**
 * Walk directory tree recursively according to glob pattern parts.
 * @param {string} dir - Current directory
 * @param {number} segIdx - Current segment index in parts
 * @param {string[]} parts - Glob pattern parts
 * @param {string} cwd - Current working directory
 * @param {string[]} results - Accumulated results
 */
function walk(dir, segIdx, parts, cwd, results) {
  if (segIdx >= parts.length) {
    const rel = path.relative(cwd, dir);
    results.push(rel || '.');
    return;
  }
  const seg = parts[segIdx];
  if (seg === '**') {
    walk(dir, segIdx + 1, parts, cwd, results);
    const entries = readDirectoryEntries(dir);
    for (const e of entries) {
      if (!e.isDirectory() || e.name === '.' || e.name === '..') {
        continue;
      }
      walk(path.join(dir, e.name), segIdx, parts, cwd, results);
    }
    return;
  }
  const hasStar = seg.includes('*');
  if (!hasStar) {
    const nextDir = path.join(dir, seg);
    if (existsSync(nextDir)) {
      walk(nextDir, segIdx + 1, parts, cwd, results);
    }
    return;
  }
  const entries = readDirectoryEntries(dir);
  const re = segmentRegex(seg);
  for (const e of entries) {
    if (re.test(e.name)) {
      walk(path.join(dir, e.name), segIdx + 1, parts, cwd, results);
    }
  }
}

/**
 * Safely read directory entries, ignoring errors.
 * @param {string} dir - Directory to read
 * @returns {fs.Dirent[]} Array of directory entries
 */
function readDirectoryEntries(dir) {
  try {
    return fs.readdirSync(dir, { withFileTypes: true });
  } catch {
    return [];
  }
}

/**
 * Safely check if path exists, ignoring errors.
 * @param {string} path - Path to check
 * @returns {boolean} True if path exists
 */
function existsSync(path) {
  try {
    return fs.existsSync(path);
  } catch {
    return false;
  }
}

/**
 * Expand one glob pattern from cwd. Returns paths relative to cwd.
 * Supports * in segments and ** as a segment (zero or more path segments).
 */
export function globSync(pattern, cwd = process.cwd()) {
  const normalized = path.normalize(pattern);
  const isAbsolute = path.isAbsolute(normalized);
  const root = path.parse(normalized).root;
  const parts = (isAbsolute ? normalized.slice(root.length) : normalized)
    .split(path.sep)
    .filter((p) => p.length > 0);
  if (parts.length === 0) {
    return [];
  }
  const results = [];
  const startDir = isAbsolute ? root : cwd;
  walk(startDir, 0, parts, cwd, results);
  return results;
}