mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
Various synced folder enhancements (#1596)
* Add explicitFolders support to syncedFolder Adds an `explicitFolders` property to `TargetSource` that is expanded from Glob patterns and passed through to `PBXFileSystemSynchronizedRootGroup`. * Fix syncedFolder sources ignoring createIntermediateGroups When createIntermediateGroups was enabled and a syncedFolder source had a multi-component path (e.g. SyncedParent/SyncedChild), two things went wrong: 1. The synced folder was unconditionally added to rootGroups, causing it to appear both at the project root and inside the correct intermediate parent group. 2. The synced folder kept its full project-relative path instead of being made relative to its parent group, so Xcode concatenated them into a wrong path (e.g. SyncedParent/SyncedParent/SyncedChild). * Enhance PBXFileElement to recognize synced folders as groups that can be sorted * Fix membership exceptions for nested synced folder with intermediate groups * Update Changelog
This commit is contained in:
@@ -1459,29 +1459,30 @@ public class PBXProjGenerator {
|
||||
}
|
||||
|
||||
// add fileSystemSynchronizedGroups
|
||||
let synchronizedRootGroups = sourceFiles.compactMap { $0.fileReference as? PBXFileSystemSynchronizedRootGroup }
|
||||
let synchronizedRootGroups: [PBXFileSystemSynchronizedRootGroup] = sourceFiles.compactMap { sourceFile in
|
||||
guard let syncedGroup = sourceFile.fileReference as? PBXFileSystemSynchronizedRootGroup else { return nil }
|
||||
|
||||
configureMembershipExceptions(
|
||||
for: syncedGroup,
|
||||
path: sourceFile.path,
|
||||
target: target,
|
||||
targetObject: targetObject,
|
||||
infoPlistFiles: infoPlistFiles
|
||||
)
|
||||
return syncedGroup
|
||||
}
|
||||
if !synchronizedRootGroups.isEmpty {
|
||||
for syncedGroup in synchronizedRootGroups {
|
||||
configureMembershipExceptions(
|
||||
for: syncedGroup,
|
||||
target: target,
|
||||
targetObject: targetObject,
|
||||
infoPlistFiles: infoPlistFiles
|
||||
)
|
||||
}
|
||||
targetObject.fileSystemSynchronizedGroups = synchronizedRootGroups
|
||||
}
|
||||
}
|
||||
|
||||
private func configureMembershipExceptions(
|
||||
for syncedGroup: PBXFileSystemSynchronizedRootGroup,
|
||||
path syncedPath: Path,
|
||||
target: Target,
|
||||
targetObject: PBXTarget,
|
||||
infoPlistFiles: [Config: String]
|
||||
) {
|
||||
guard let syncedGroupPath = syncedGroup.path else { return }
|
||||
let syncedPath = (project.basePath + Path(syncedGroupPath)).normalize()
|
||||
|
||||
guard let targetSource = target.sources.first(where: {
|
||||
(project.basePath + $0.path).normalize() == syncedPath
|
||||
}) else { return }
|
||||
@@ -1692,13 +1693,13 @@ extension Platform {
|
||||
}
|
||||
|
||||
extension PBXFileElement {
|
||||
/// - returns: `true` if the element is a group or a folder reference. Likely an SPM package.
|
||||
/// - returns: `true` if the element is a group, a folder reference (likely an SPM package), or a synced folder.
|
||||
var isGroupOrFolder: Bool {
|
||||
self is PBXGroup || (self as? PBXFileReference)?.lastKnownFileType == "folder"
|
||||
self is PBXGroup || self is PBXFileSystemSynchronizedRootGroup || (self as? PBXFileReference)?.lastKnownFileType == "folder"
|
||||
}
|
||||
|
||||
public func getSortOrder(groupSortPosition: SpecOptions.GroupSortPosition) -> Int {
|
||||
if type(of: self).isa == "PBXGroup" {
|
||||
if self is PBXGroup || self is PBXFileSystemSynchronizedRootGroup {
|
||||
switch groupSortPosition {
|
||||
case .top: return -1
|
||||
case .bottom: return 1
|
||||
|
||||
@@ -399,6 +399,20 @@ class SourceGenerator {
|
||||
)
|
||||
}
|
||||
|
||||
/// Expands glob patterns in `explicitFolders` relative to the synced root path.
|
||||
private func resolveExplicitFolders(targetSource: TargetSource) -> [String] {
|
||||
let rootSourcePath = project.basePath + targetSource.path
|
||||
|
||||
return targetSource.explicitFolders.flatMap { pattern in
|
||||
let matches = Glob(pattern: "\(rootSourcePath)/\(pattern)")
|
||||
.map { Path($0) }
|
||||
.filter { $0.isDirectory }
|
||||
.compactMap { try? $0.relativePath(from: rootSourcePath).string }
|
||||
.sorted()
|
||||
return matches.isEmpty ? [pattern] : matches
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the path is not in any default or TargetSource excludes
|
||||
func isIncludedPath(_ path: Path, excludePaths: Set<Path>, includePaths: SortedArray<Path>?) -> Bool {
|
||||
return !defaultExcludedFiles.contains(where: { path.lastComponent == $0 })
|
||||
@@ -695,6 +709,7 @@ class SourceGenerator {
|
||||
case .syncedFolder:
|
||||
|
||||
let relativePath = (try? path.relativePath(from: project.basePath)) ?? path
|
||||
let resolvedExplicitFolders = resolveExplicitFolders(targetSource: targetSource)
|
||||
|
||||
let syncedRootGroup = PBXFileSystemSynchronizedRootGroup(
|
||||
sourceTree: .group,
|
||||
@@ -702,13 +717,14 @@ class SourceGenerator {
|
||||
name: targetSource.name,
|
||||
explicitFileTypes: [:],
|
||||
exceptions: [],
|
||||
explicitFolders: []
|
||||
explicitFolders: resolvedExplicitFolders
|
||||
)
|
||||
addObject(syncedRootGroup)
|
||||
sourceReference = syncedRootGroup
|
||||
|
||||
// TODO: adjust if hasCustomParent == true
|
||||
rootGroups.insert(syncedRootGroup)
|
||||
if !(createIntermediateGroups || hasCustomParent) || path.parent() == project.basePath {
|
||||
rootGroups.insert(syncedRootGroup)
|
||||
}
|
||||
|
||||
let sourceFile = generateSourceFile(
|
||||
targetType: targetType,
|
||||
@@ -725,6 +741,7 @@ class SourceGenerator {
|
||||
try makePathRelative(for: sourceReference, at: path)
|
||||
} else if createIntermediateGroups {
|
||||
createIntermediaGroups(for: sourceReference, at: sourcePath)
|
||||
try makePathRelative(for: sourceReference, at: sourcePath)
|
||||
}
|
||||
|
||||
return sourceFiles
|
||||
|
||||
Reference in New Issue
Block a user