Package net.minecraftforge.gradle.tasks

Source Code of net.minecraftforge.gradle.tasks.ProcessSrcJarTask$RelFile

package net.minecraftforge.gradle.tasks;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import net.minecraftforge.gradle.common.Constants;
import net.minecraftforge.gradle.delayed.DelayedFile;
import net.minecraftforge.gradle.patching.ContextualPatch;
import net.minecraftforge.gradle.patching.ContextualPatch.PatchStatus;
import net.minecraftforge.gradle.tasks.abstractutil.EditJarTask;

import org.gradle.api.file.FileCollection;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;

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

public class ProcessSrcJarTask extends EditJarTask
{
    private List<ResourceHolder> stages  = new LinkedList<ResourceHolder>();

    @Input
    private int                  maxFuzz = 0;

    private ContextProvider      PROVIDER;

    @Override
    public String asRead(String file)
    {
        return file;
    }

    @Override
    public void doStuffBefore() throws Throwable
    {
        PROVIDER = new ContextProvider(sourceMap);
    }

    @Override
    public void doStuffMiddle() throws Throwable
    {
        for (ResourceHolder stage : stages)
        {
            getLogger().lifecycle("Injecting {} files", stage.name);
            for (RelFile rel : stage.getRelInjects())
            {
                String relative = rel.getRelative();

                if (sourceMap.containsKey(relative) || resourceMap.containsKey("relative"))
                    continue; //ignore duplicates.

                if (relative.endsWith(".java"))
                {
                    sourceMap.put(relative, Files.toString(rel.file, Charset.defaultCharset()));
                }
                else
                {
                    resourceMap.put(relative, Files.asByteSource(rel.file).read());
                }
            }
           
            getLogger().lifecycle("Applying {} patches", stage.name);
            applyPatchStage(stage.name, stage.getPatchFiles());
        }
    }

    public void applyPatchStage(String stage, FileCollection patchFiles) throws Throwable
    {
        getLogger().info("Reading patches for stage {}", stage);
        ArrayList<PatchedFile> patches = readPatches(patchFiles);

        boolean fuzzed = false;

        getLogger().info("Applying patches for stage {}", stage);

        Throwable failure = null;

        for (PatchedFile patch : patches)
        {
            List<ContextualPatch.PatchReport> errors = patch.patch.patch(false);
            for (ContextualPatch.PatchReport report : errors)
            {
                // catch failed patches
                if (!report.getStatus().isSuccess())
                {
                    File reject = patch.makeRejectFile();
                    if (reject.exists())
                    {
                        reject.delete();
                    }
                    getLogger().log(LogLevel.ERROR, "Patching failed: {} {}", PROVIDER.strip(report.getTarget()), report.getFailure().getMessage());
                    // now spit the hunks
                    int failed = 0;
                    for (ContextualPatch.HunkReport hunk : report.getHunks())
                    {
                        // catch the failed hunks
                        if (!hunk.getStatus().isSuccess())
                        {
                            failed++;
                            getLogger().error("  " + hunk.getHunkID() + ": " + (hunk.getFailure() != null ? hunk.getFailure().getMessage() : "") + " @ " + hunk.getIndex());
                            Files.append(String.format("++++ REJECTED PATCH %d\n", hunk.getHunkID()), reject, Charsets.UTF_8);
                            Files.append(Joiner.on('\n').join(hunk.hunk.lines), reject, Charsets.UTF_8);
                            Files.append(String.format("\n++++ END PATCH\n"), reject, Charsets.UTF_8);
                        }
                        else if (hunk.getStatus() == PatchStatus.Fuzzed)
                        {
                            getLogger().info("  " + hunk.getHunkID() + " fuzzed " + hunk.getFuzz() + "!");
                        }
                    }
                    getLogger().log(LogLevel.ERROR, "  {}/{} failed", failed, report.getHunks().size());
                    getLogger().log(LogLevel.ERROR, "  Rejects written to {}", reject.getAbsolutePath());

                    if (failure == null)
                        failure = report.getFailure();
                }
                // catch fuzzed patches
                else if (report.getStatus() == ContextualPatch.PatchStatus.Fuzzed)
                {
                    getLogger().log(LogLevel.INFO, "Patching fuzzed: {}", PROVIDER.strip(report.getTarget()));

                    // set the boolean for later use
                    fuzzed = true;

                    // now spit the hunks
                    for (ContextualPatch.HunkReport hunk : report.getHunks())
                    {
                        // catch the failed hunks
                        if (hunk.getStatus() == PatchStatus.Fuzzed)
                        {
                            getLogger().info("  {} fuzzed {}!", hunk.getHunkID(), hunk.getFuzz());
                        }
                    }

                    if (failure == null)
                        failure = report.getFailure();
                }

                // sucesful patches
                else
                {
                    getLogger().info("Patch succeeded: {}", PROVIDER.strip(report.getTarget()));
                }
            }
        }

        if (fuzzed)
        {
            getLogger().lifecycle("Patches Fuzzed!");
        }
    }

    private ArrayList<PatchedFile> readPatches(FileCollection patchFiles) throws IOException
    {
        ArrayList<PatchedFile> patches = new ArrayList<PatchedFile>();

        for (File file : patchFiles.getFiles())
        {
            if (file.getPath().endsWith(".patch"))
            {
                patches.add(readPatch(file));
            }
        }

        return patches;
    }

    public PatchedFile readPatch(File file) throws IOException
    {
        getLogger().debug("Reading patch file: {}");
        return new PatchedFile(file);
    }

    @InputFiles
    public FileCollection getAllPatches()
    {
        FileCollection col = null;

        for (ResourceHolder holder : stages)
            if (col == null)
                col = holder.getPatchFiles();
            else
                col = getProject().files(col, holder.getPatchFiles());

        return col;
    }

    @InputFiles
    public FileCollection getAllInjects()
    {
        FileCollection col = null;

        for (ResourceHolder holder : stages)
            if (col == null)
                col = holder.getInjects();
            else
                col = getProject().files(col, holder.getInjects());

        return col;
    }

    public void addStage(String name, DelayedFile patchDir, DelayedFile... injects)
    {
        stages.add(new ResourceHolder(name, patchDir, Arrays.asList(injects)));
    }
   
    public void addStage(String name, DelayedFile patchDir)
    {
        stages.add(new ResourceHolder(name, patchDir));
    }

    @Override
    public void doStuffAfter() throws Throwable
    {
    }

    public int getMaxFuzz()
    {
        return maxFuzz;
    }

    public void setMaxFuzz(int maxFuzz)
    {
        this.maxFuzz = maxFuzz;
    }

    private class PatchedFile
    {
        public final File            fileToPatch;
        public final ContextualPatch patch;

        public PatchedFile(File file) throws IOException
        {
            this.fileToPatch = file;
            this.patch = ContextualPatch.create(Files.toString(file, Charset.defaultCharset()), PROVIDER).setAccessC14N(true).setMaxFuzz(getMaxFuzz());
        }

        public File makeRejectFile()
        {
            return new File(fileToPatch.getParentFile(), fileToPatch.getName() + ".rej");
        }
    }

    /**
     * A private inner class to be used with the FmlPatches
     */
    private class ContextProvider implements ContextualPatch.IContextProvider
    {
        private Map<String, String> fileMap;

        private final int           STRIP = 3;

        public ContextProvider(Map<String, String> fileMap)
        {
            this.fileMap = fileMap;
        }

        public String strip(String target)
        {
            target = target.replace('\\', '/');
            int index = 0;
            for (int x = 0; x < STRIP; x++)
            {
                index = target.indexOf('/', index) + 1;
            }
            return target.substring(index);
        }

        @Override
        public List<String> getData(String target)
        {
            target = strip(target);

            if (fileMap.containsKey(target))
            {
                String[] lines = fileMap.get(target).split("\r\n|\r|\n");
                List<String> ret = new ArrayList<String>();
                for (String line : lines)
                {
                    ret.add(line);
                }
                return ret;
            }

            return null;
        }

        @Override
        public void setData(String target, List<String> data)
        {
            target = strip(target);
            fileMap.put(target, Joiner.on(Constants.NEWLINE).join(data));
        }
    }

    /**
     * A little resource holder to make my life a teeny bit easier..
     */
    private final class ResourceHolder
    {
        final String            name;
        final DelayedFile       patchDir;
        final List<DelayedFile> srcDirs;

        public ResourceHolder(String name, DelayedFile patchDir, List<DelayedFile> srcDirs)
        {
            this.name = name;
            this.patchDir = patchDir;
            this.srcDirs = srcDirs;
        }
       
        public ResourceHolder(String name, DelayedFile patchDir)
        {
            this.name = name;
            this.patchDir = patchDir;
            this.srcDirs = new ArrayList<DelayedFile>(0);
        }

        public FileCollection getPatchFiles()
        {
            File patch = getProject().file(patchDir);
            if (patch.isDirectory())
                return getProject().fileTree(patch);
            else if (patch.getPath().endsWith("zip") || patch.getPath().endsWith("jar"))
                return getProject().zipTree(patch);
            else
                return getProject().files(patch);
        }

        public FileCollection getInjects()
        {
            ArrayList<FileCollection> trees = new ArrayList<FileCollection>(srcDirs.size());
            for (DelayedFile f : srcDirs)
                trees.add(getProject().fileTree(f.call()));
            return getProject().files(trees);
        }

        public List<RelFile> getRelInjects()
        {
            LinkedList<RelFile> files = new LinkedList<RelFile>();

            for (DelayedFile df : srcDirs)
            {
                File dir = df.call();
               
                if (dir.isDirectory())
                {
                    for (File f : getProject().fileTree(dir))
                    {
                        files.add(new RelFile(f, dir));
                    }
                }
                else
                {
                    files.add(new RelFile(dir, dir.getParentFile()));
                }
            }
            return files;
        }
    }

    private static final class RelFile
    {
        public final File file;
        public final File root;

        public RelFile(File file, File root)
        {
            this.file = file;
            this.root = root;
        }

        public String getRelative()
        {
            return file.getAbsolutePath().substring(root.getAbsolutePath().length() + 1).replace('\\', '/');
        }
    }
}
TOP

Related Classes of net.minecraftforge.gradle.tasks.ProcessSrcJarTask$RelFile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.