package hudson.plugins.analysis.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import hudson.FilePath;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.plugins.analysis.util.model.FileAnnotation;

/**
 * A base class for {@link Blamer} implementations.
 *
 * @author Lukas Krose
 */
public abstract class AbstractBlamer implements Blamer {
    /** The current run */
    private final AbstractBuild<?, ?> build;
    /** the current workspace */
    private final FilePath workspace;
    private TaskListener listener;
    /** The PluginLogger to log ,essages */
    private final PluginLogger logger;

    /**
     * Creates a new {@link AbstractBlamer}.
     *
     * @param build     the build
     * @param workspace the workspace of the build
     * @param listener
     * @param logger    the plugin logger
     */
    public AbstractBlamer(final AbstractBuild<?, ?> build, final FilePath workspace, final TaskListener listener, final PluginLogger logger) {
        this.build = build;
        this.workspace = workspace;
        this.listener = listener;
        this.logger = logger;
    }

    /**
     * Extracts the relative file names of the files that contain annotations
     * to make sure every file is blamed only once.
     *
     * @param annotations the annotations to extract the file names from
     * @return a mapping of absolute to relative file names of the conflicting files
     */
    protected Map<String, BlameRequest> extractConflictingFiles(final Set<FileAnnotation> annotations) {
        String workspacePath = workspace.getRemote().replace('\\', '/');
        Map<String, BlameRequest> pathsByFileName = new HashMap<String, BlameRequest>();

        for (FileAnnotation annotation : annotations) {
            if (annotation.getPrimaryLineNumber() > 0) {
                String absoluteFileName = annotation.getFileName();
                if (pathsByFileName.containsKey(absoluteFileName)) {
                    BlameRequest blame = pathsByFileName.get(absoluteFileName);
                    blame.addLineNumber(annotation.getPrimaryLineNumber());
                }
                else {
                    if (absoluteFileName.startsWith(workspacePath)) {
                        String relativeFileName = annotation.getFileName().substring(workspacePath.length());
                        if (relativeFileName.startsWith("/") || relativeFileName.startsWith("\\")) {
                            relativeFileName = relativeFileName.substring(1);
                        }
                        pathsByFileName.put(absoluteFileName, new BlameRequest(relativeFileName, annotation.getPrimaryLineNumber()));
                    }
                    else {
                        log("Skipping non-workspace file " + annotation.getFileName());
                    }
                }
            }
        }
        return pathsByFileName;
    }

    /**
     * Logs the specified message.
     *
     * @param message the message (format string)
     * @param args    the arguments for the message format
     */
    protected final void log(final String message, final Object... args) {
        logger.log("<Git Blamer> " + String.format(message, args));
    }

    protected FilePath getWorkspace() {
        return workspace;
    }

    protected AbstractBuild<?, ?> getBuild() {
        return build;
    }

    protected TaskListener getListener() {
        return listener;
    }
}

@@ -32,16 +32,65 @@
 .util;%0A%0A
+import java.io.File;%0Aimport java.io.IOException;%0A
 import j
@@ -657,17 +657,17 @@
  to log 
-,
+m
 essages 
@@ -876,16 +876,66 @@
 listener
+  task listener to print git logging statements to
 %0A     * 
@@ -1675,81 +1675,8 @@
 ) %7B%0A
-        String workspacePath = workspace.getRemote().replace('%5C%5C', '/');%0A
     
@@ -1761,16 +1761,67 @@
 st%3E();%0A%0A
+        String workspacePath = getWorkspacePath();%0A
         
@@ -1959,32 +1959,49 @@
 oluteFileName = 
+getCanonicalPath(
 annotation.getFi
@@ -2008,16 +2008,17 @@
 leName()
+)
 ;%0A      
@@ -2906,134 +2906,563 @@
 ile 
-%22 + annotation.getFileName());%0A                    %7D%0A                %7D%0A            %7D%0A        %7D%0A        return pathsByFileName;
+%25s (workspace = %25s, absolute = %25s)%22,%0A                                annotation.getFileName(), workspacePath, absoluteFileName);%0A                    %7D%0A                %7D%0A            %7D%0A        %7D%0A        return pathsByFileName;%0A    %7D%0A%0A    private String getWorkspacePath() %7B%0A        return getCanonicalPath(workspace.getRemote().replace('%5C%5C', '/'));%0A    %7D%0A%0A    private String getCanonicalPath(final String path) %7B%0A        try %7B%0A            return new File(path).getCanonicalPath();%0A        %7D%0A        catch (IOException e) %7B%0A            return path;%0A        %7D
 %0A   

Use canonical path when comparing with workspace.