pbxspec::PBX::FileType::shared_ptr FileTypeResolver::
Resolve(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::PBX::FileReference::shared_ptr const &fileReference, std::string const &filePath)
{
    if (!fileReference->explicitFileType().empty()) {
        if (pbxspec::PBX::FileType::shared_ptr const &fileType = specManager->fileType(fileReference->explicitFileType(), domains)) {
            return fileType;
        }
    }

    if (!fileReference->lastKnownFileType().empty()) {
        if (pbxspec::PBX::FileType::shared_ptr const &fileType = specManager->fileType(fileReference->lastKnownFileType(), domains)) {
            return fileType;
        }
    }

    return Resolve(specManager, domains, filePath);
}
pbxspec::PBX::FileType::shared_ptr FileTypeResolver::
Resolve(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::XC::VersionGroup::shared_ptr const &versionGroup, std::string const &filePath)
{
    if (!versionGroup->versionGroupType().empty()) {
        if (pbxspec::PBX::FileType::shared_ptr const &fileType = specManager->fileType(versionGroup->versionGroupType(), domains)) {
            return fileType;
        }
    }

    return Resolve(specManager, domains, filePath);
}
Example #3
0
static Target::BuildRules::BuildRule::shared_ptr
ProjectBuildRule(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxproj::PBX::BuildRule::shared_ptr const &projBuildRule)
{
    pbxspec::PBX::Tool::shared_ptr tool = nullptr;
    std::string TS = projBuildRule->compilerSpec();
    if (TS != "com.apple.compilers.proxy.script") {
        tool = specManager->tool(TS, domains);
        if (tool == nullptr) {
            tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->compiler(TS, domains));
        }
        if (tool == nullptr) {
            tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->linker(TS, domains));
        }

        if (tool == nullptr) {
            fprintf(stderr, "warning: couldn't find tool %s specified in build rule\n", TS.c_str());
            return nullptr;
        }
    }

    pbxspec::PBX::FileType::vector fileTypes;
    std::string FT = projBuildRule->fileType();
    if (FT != "pattern.proxy") {
        pbxspec::PBX::FileType::shared_ptr fileType = specManager->fileType(FT, domains);
        if (fileType == nullptr) {
            fprintf(stderr, "warning: couldn't find input file type %s specified in build rule\n", FT.c_str());
            return nullptr;
        }
        fileTypes.push_back(fileType);
    }

    std::vector<pbxsetting::Value> outputFiles;
    for (std::string const &outputFile : projBuildRule->outputFiles()) {
        outputFiles.push_back(pbxsetting::Value::Parse(outputFile));
    }

    return std::make_shared <Target::BuildRules::BuildRule> (Target::BuildRules::BuildRule(
        projBuildRule->filePatterns(),
        fileTypes,
        tool,
        projBuildRule->script(),
        outputFiles
    ));
}
Example #4
0
static Target::BuildRules::BuildRule::shared_ptr
SpecificationBuildRule(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, pbxspec::PBX::BuildRule::shared_ptr const &specBuildRule)
{
    if (!specBuildRule->compilerSpec()) {
        return nullptr;
    }

    std::string const &TS = *specBuildRule->compilerSpec();
    pbxspec::PBX::Tool::shared_ptr tool = specManager->tool(TS, domains);
    if (tool == nullptr) {
        tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->compiler(TS, domains));
    }
    if (tool == nullptr) {
        tool = std::static_pointer_cast<pbxspec::PBX::Tool>(specManager->linker(TS, domains));
    }

    if (tool == nullptr) {
        return nullptr;
    }

    pbxspec::PBX::FileType::vector fileTypes;
    if (specBuildRule->fileTypes()) {
        for (std::string const &FT : *specBuildRule->fileTypes()) {
            pbxspec::PBX::FileType::shared_ptr fileType = specManager->fileType(FT, domains);
            if (fileType == nullptr) {
                return nullptr;
            }
            fileTypes.push_back(fileType);
        }
    }

    return std::make_shared <Target::BuildRules::BuildRule> (Target::BuildRules::BuildRule(
        std::string(),
        fileTypes,
        tool,
        std::string(),
        std::vector<pbxsetting::Value>()
    ));
}
pbxspec::PBX::FileType::shared_ptr FileTypeResolver::
Resolve(pbxspec::Manager::shared_ptr const &specManager, std::vector<std::string> const &domains, std::string const &filePath)
{
    bool isReadable = FSUtil::TestForRead(filePath);
    bool isFolder = isReadable && FSUtil::TestForDirectory(filePath);

    std::string fileExtension = FSUtil::GetFileExtension(filePath);
    std::string fileName = FSUtil::GetBaseName(filePath);

    std::ifstream fileHandle;
    std::vector<uint8_t> fileContents;

    // Reverse first so more specific file types are processed first.
    std::vector<pbxspec::PBX::FileType::shared_ptr> const &fileTypes = specManager->fileTypes(domains);
    ext::optional<std::vector<pbxspec::PBX::FileType::shared_ptr>> result = SortedFileTypes(fileTypes);
    if (!result) {
        fprintf(stderr, "error: cycle creating file type graph\n");
        return nullptr;
    }

    std::vector<pbxspec::PBX::FileType::shared_ptr> const &sortedFileTypes = *result;
    for (pbxspec::PBX::FileType::shared_ptr const &fileType : sortedFileTypes) {
        if (isReadable && fileType->isFolder() != isFolder) {
            continue;
        }

        bool empty = true;

        if (fileType->extensions()) {
            empty = false;
            bool matched = false;

            for (std::string const &extension : *fileType->extensions()) {
                // TODO(grp): Is this correct? Needed for handling ".S" as ".s", but might be over-broad.
                if (strcasecmp(extension.c_str(), fileExtension.c_str()) == 0) {
                    matched = true;
                }
            }

            if (!matched) {
                continue;
            }
        }


        if (fileType->prefix()) {
            empty = false;
            bool matched = false;

            for (std::string const &prefix : *fileType->prefix()) {
                if (fileName.find(prefix) == 0) {
                    matched = true;
                }
            }

            if (!matched) {
                continue;
            }
        }

        if (fileType->filenamePatterns()) {
            empty = false;
            bool matched = false;

            for (std::string const &pattern : *fileType->filenamePatterns()) {
                if (Wildcard::Match(pattern, fileName)) {
                    matched = true;
                }
            }

            if (!matched) {
                continue;
            }
        }

        if (isReadable && fileType->permissions()) {
            empty = false;
            bool matched = false;

            std::string const &permissions = *fileType->permissions();
            if (permissions == "read") {
                matched = isReadable;
            } else if (permissions == "write") {
                matched = FSUtil::TestForWrite(filePath);
            } else if (permissions == "executable") {
                matched = FSUtil::TestForExecute(filePath);
            } else {
                fprintf(stderr, "warning: unhandled permission %s\n", permissions.c_str());
            }

            if (!matched) {
                continue;
            }
        }

        // TODO(grp): Support TypeCodes. Not very important.

        if (isReadable && fileType->magicWords()) {
            empty = false;
            bool matched = false;

            for (std::vector<uint8_t> const &magicWord : *fileType->magicWords()) {
                if (fileContents.size() < magicWord.size()) {
                    if (!fileHandle.is_open()) {
                        fileHandle.open(fileName, std::ios::in | std::ios::binary);
                        if (!fileHandle.good()) {
                            continue;
                        }
                    }

                    size_t offset = fileContents.size();
                    fileContents.resize(magicWord.size());
                    fileHandle.read((char *)&fileContents[offset], magicWord.size() - offset);
                    if (!fileHandle.good()) {
                        fileContents.resize(offset);
                        continue;
                    }
                }

                if (std::equal(magicWord.begin(), magicWord.end(), fileContents.begin())) {
                    matched = true;
                }
            }

            if (!matched) {
                continue;
            }
        }

        //
        // Matched no checks.
        //
        if (empty) {
            continue;
        }

        //
        // Matched all checks.
        //
        return fileType;
    }

    pbxspec::PBX::FileType::shared_ptr fileType = (isFolder ? specManager->fileType("folder", domains) : specManager->fileType("file", domains));
    return fileType;
}