All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.minecraftforge.gradle.user.TaskSourceCopy Maven / Gradle / Ivy

/*
 * A Gradle plugin for the creation of Minecraft mods and MinecraftForge plugins.
 * Copyright (C) 2013-2019 Minecraft Forge
 * Copyright (C) 2020-2021 anatawa12 and other contributors
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
 */
package net.minecraftforge.gradle.user;

import groovy.lang.Closure;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

import org.gradle.api.DefaultTask;
import org.gradle.api.file.DirectoryTree;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTree;
import org.gradle.api.file.SourceDirectorySet;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.util.PatternSet;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

public class TaskSourceCopy extends DefaultTask
{
    @InputFiles
    SourceDirectorySet      source;

    @Input
    HashMap replacements = new HashMap();

    @Input
    ArrayList       includes     = new ArrayList();

    @OutputDirectory
    Object             output;

    @SuppressWarnings("unchecked")
    @TaskAction
    public void doTask() throws IOException
    {
        // get the include/exclude patterns from the source (this is different than what's returned by getFilter)
        PatternSet patterns = new PatternSet();
        patterns.setIncludes(source.getIncludes());
        patterns.setExcludes(source.getExcludes());

        // get output
        File out = getOutput();
        if (out.exists())
            deleteDir(out);

        out.mkdirs();
        out = out.getCanonicalFile();

        // resolve replacements
        HashMap repl = new HashMap(replacements.size());
        for (Entry e : replacements.entrySet())
        {
            if (e.getKey() == null || e.getValue() == null)
                continue; // we dont deal with nulls.

            Object val = e.getValue();
            while (val instanceof Closure)
                val = ((Closure) val).call();

            repl.put(Pattern.quote(e.getKey()), val.toString());
        }

        getLogger().debug("REPLACE >> " + repl);

        // start traversing tree
        for (DirectoryTree dirTree : source.getSrcDirTrees())
        {
            File dir = dirTree.getDir();
            getLogger().debug("PARSING DIR >> " + dir);

            // handle nonexistant srcDirs
            if (!dir.exists() || !dir.isDirectory())
                continue;
            else
                dir = dir.getCanonicalFile();

            // this could be written as .matching(source), but it doesn't actually work
            // because later on gradle casts it directly to PatternSet and crashes
            FileTree tree = getProject().fileTree(dir).matching(source.getFilter()).matching(patterns);

            for (File file : tree)
            {
                File dest = getDest(file, dir, out);
                dest.getParentFile().mkdirs();
                dest.createNewFile();

                if (isIncluded(file))
                {
                    getLogger().debug("PARSING FILE IN >> " + file);
                    String text = Files.toString(file, Charsets.UTF_8);

                    for (Entry entry : repl.entrySet())
                        text = text.replaceAll(entry.getKey(), entry.getValue());

                    getLogger().debug("PARSING FILE OUT >> " + dest);
                    Files.write(text, dest, Charsets.UTF_8);
                }
                else
                {
                    Files.copy(file, dest);
                }
            }
        }
    }

    private File getDest(File in, File base, File baseOut) throws IOException
    {
        String relative = in.getCanonicalPath().replace(base.getCanonicalPath(), "");
        return new File(baseOut, relative);
    }

    private boolean isIncluded(File file) throws IOException
    {
        if (includes.isEmpty())
            return true;

        String path = file.getCanonicalPath().replace('\\', '/');
        for (String include : includes)
        {
            if (path.endsWith(include.replace('\\', '/')))
                return true;
        }

        return false;
    }

    private boolean deleteDir(File dir)
    {
        if (dir.exists())
        {
            File[] files = dir.listFiles();
            if (null != files)
            {
                for (int i = 0; i < files.length; i++)
                {
                    if (files[i].isDirectory())
                    {
                        deleteDir(files[i]);
                    }
                    else
                    {
                        files[i].delete();
                    }
                }
            }
        }
        return (dir.delete());
    }

    public File getOutput()
    {
        return getProject().file(output);
    }

    public void setOutput(Object output)
    {
        this.output = output;
    }

    public void setSource(SourceDirectorySet source)
    {
        this.source = source;
    }

    public FileCollection getSource()
    {
        return source;
    }

    public void replace(String key, Object val)
    {
        replacements.put(key, val);
    }

    public void replace(Map map)
    {
        replacements.putAll(map);
    }

    public HashMap getReplacements()
    {
        return replacements;
    }

    public void include(String str)
    {
        includes.add(str);
    }

    public void include(List strs)
    {
        includes.addAll(strs);
    }

    public ArrayList getIncudes()
    {
        return includes;
    }
}