text:
"use strict";

/**
 * This module contains common git utility methods that require NodeGit.
 * Otherwise, put them in git_util_fast to optimize their load time.
 */

const assert       = require("chai").assert;
const ChildProcess = require("child-process-promise");
const co           = require("co");
const colors       = require("colors");
const fs           = require("fs-promise");
const NodeGit      = require("nodegit");
const path         = require("path");

const ConfigUtil          = require("./config_util");
const Hook                = require("./hook");
const GitUtilFast         = require("./git_util_fast");
const UserError           = require("./user_error");

/**
 * Create a branch having the specified `branchName` in the specified `repo`
 * pointing to the current head.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String} branchName
 * @return {NodeGit.Branch}
 */
exports.createBranchFromHead = co.wrap(function *(repo, branchName) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(branchName);

    const head = yield repo.getHeadCommit();
    return yield repo.createBranch(branchName,
                                   head,
                                   0,
                                   yield ConfigUtil.defaultSignature(repo),
                                   "git-meta branch");
});

/**
 * Return the branch having the specified local `branchName` in the specified
 * `repo`, or null if `repo` does not contain a branch with that name.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String} branchName
 * @return {NodeGit.Reference|null}
 */
exports.findBranch = co.wrap(function *(repo, branchName) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(branchName);

    try {
        return yield repo.getBranch(branchName);
    }
    catch (e) {
        return null;
    }
});

/**
 * Return the tracking information for the specified `branch`, or null if it
 * has none.
 *
 * @param {NodeGit.Repository} repo
 * @param {NodeGit.Reference} branch
 * @return {Object|null}
 * @return {String|null} return.remoteName
 * @return {String|null} return.pushRemoteName
 * @return {String} return.branchName
 */
exports.getTrackingInfo = co.wrap(function *(repo, branch) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(branch, NodeGit.Reference);
    let upstream;
    try {
        upstream = yield NodeGit.Branch.upstream(branch);
    }
    catch (e) {
        // No way to check for this other than to catch.
        return null;
    }
    const name = upstream.shorthand();
    const parts = name.split("/");
    const config = yield repo.config();

    // Try to read a 'pushRemote' for the branch.

    let pushRemote = yield ConfigUtil.getConfigString(
                                     config,
                                    `branch.${branch.shorthand()}.pushRemote`);

    // If no 'pushRemote', try to read a 'pushDefault' for the repo.

    if (null === pushRemote) {
        pushRemote = yield ConfigUtil.getConfigString(config,
                                                      "remote.pushDefault");
    }

    if (1 === parts.length) {
        return {
            branchName: parts[0],
            remoteName: null,
            pushRemoteName: pushRemote,
        };
    }
    const remoteName = parts.shift();
    return {
        branchName: parts.join("/"),
        remoteName: remoteName,
        pushRemoteName: pushRemote || remoteName,
    };
});

/**
 * If the current branch branch in the specified `repo` tracks another branch,
 * return its name (qualified by $remote-name if it's tracking a remote
 * branch), or return null if it tracks no branch.
 *
 * @param {NodeGit.Repository} repo
 * @return {String|null}
 */
exports.getCurrentTrackingBranchName = co.wrap(function *(repo) {
    assert.instanceOf(repo, NodeGit.Repository);

    const head = yield repo.head();
    const tracking = yield exports.getTrackingInfo(repo, head);
    if (null === tracking) {
        return null;                                                  // RETURN
    }
    if (null === tracking.remoteName) {
        return tracking.branchName;                                   // RETURN
    }
    return `${tracking.remoteName}/${tracking.branchName}`;
});

/**
 * Return the remote associated with the upstream reference of the specified
 * `branch` in the specified `repo`.
 *
 * @param {NodeGit.Repo}      repo
 * @param {NodeGit.Reference} branch
 * @return {NodeGit.Remote|null}
 */
exports.getRemoteForBranch = co.wrap(function *(repo, branch) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(branch, NodeGit.Reference);
    const trackingInfo = yield exports.getTrackingInfo(repo, branch);
    if (null === trackingInfo || null === trackingInfo.remoteName) {
        return null;
    }
    let upstream;
    try {
        upstream = yield NodeGit.Branch.upstream(branch);
    }
    catch (e) {
        // No way to check for this other than to catch.
        return null;
    }
    return yield NodeGit.Remote.lookup(repo, trackingInfo.remoteName);
});

/**
 * Return true if the specified `repo` has a remote with the specified `name`
 * and false otherwise.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             name
 * @return {Boolean}
 */
exports.isValidRemoteName = co.wrap(function *(repo, name) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(name);

    const remotes = yield repo.getRemotes();
    return remotes.find(x => x === name) !== undefined;
});

/**
 * Return the URL for the specified `remote` in the specified `repo`, resolving
 * it to an actual path if necessary.
 *
 * @param {NodeGit.Repository} repo
 * @param {NodeGit.Remote}     remote
 * @return {String}
 */
exports.getRemoteUrl = co.wrap(function *(repo, remote) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(remote, NodeGit.Remote);
    const url = remote.url();
    if (url.startsWith(".")) {
        const resolved = path.resolve(repo.workdir(), url);
        return yield fs.realpath(resolved);                           // RETURN
    }
    return url;
});

/**
 * Return the URL for the remote from which to fetch submodule refs in the
 * specified `repo`, or null if no remote can be found.  If `repo` has a
 * current branch, and that branch has an upstream, return the URL for the
 * remote of that upstream; otherwise, if there is a remote named "origin",
 * return the URL for that remote; otherwise, return null.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @return {String|null}
 */
exports.getOriginUrl = co.wrap(function *(repo) {
    assert.instanceOf(repo, NodeGit.Repository);

    const helper = co.wrap(function *() {
        let currentBranch = null;
        try {
            currentBranch = yield repo.getCurrentBranch();
        }
        catch (e) {
            // this can fail, e.g., if the repo is empty
        }
        if (null !== currentBranch) {
            const fromBranch = yield exports.getRemoteForBranch(repo,
                                                                currentBranch);
            if (null !== fromBranch) {
                return fromBranch;
            }
        }
        try {
            return yield repo.getRemote("origin");
        }
        catch (e) {
            return null;
        }
    });
    const remote = yield helper();

    if (null !== remote) {
        return exports.getRemoteUrl(repo, remote);
    }
    return null;
});

/**
 * Return the remote branch having the specified local `branchName` in the
 * remote having the specified `remoteName` in the specified `repo`, or null if
 * no such branch exists.  The behavior is undefined unless 'remoteName' refers
 * to a remote in 'repo'.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             remoteName
 * @param {String}             branchName
 * @return {NodeGit.Reference|null}
 */
exports.findRemoteBranch = co.wrap(function *(repo, remoteName, branchName) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(remoteName);
    assert.isString(branchName);

    // TODO: need to find a way to avoid a linear search of branch names.

    const shorthand = remoteName + "/" + branchName;
    return yield exports.findBranch(repo, shorthand);
});

/**
 * Return the current repository (as located from the current working
 * directory) or throw a `UserError` exception if no git repository can be
 * located from the current directory.
 *
 * @async
 * @return {NodeGit.Repository}
 */
exports.getCurrentRepo = function () {
    const path = GitUtilFast.getRootGitDirectory();
    if (null === path) {
        throw new UserError(
            `Could not find Git directory from ${colors.red(process.cwd())}.`);
    }
    return NodeGit.Repository.open(path);
};

/**
 * Push the specified `source` branch in the specified `repo` to the specified
 * `target` branch in the specified `remote` repository.  Return null if the
 * push succeeded and string containing an error message if the push failed.
 * Attempt to allow a non-ffwd push if the specified `force` is `true`.
 * If `quiet` is true, and push was successful, silence console output.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             remote
 * @param {String}             source
 * @param {String}             target
 * @param {String}             force
 * @param {Boolean}            [quiet]
 * @return {String} [return]
 */
exports.push = co.wrap(function *(repo, remote, source, target, force, quiet) {
    // TODO: this is an awful hack because I can't yet figure out how to get
    // nodegit to work with kerberos.  For now, will shell out and use the
    // 'git' command.

    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(remote);
    assert.isString(source);
    assert.isString(target);
    assert.isBoolean(force);

    if (undefined === quiet) {
        quiet = false;
    }
    else {
        assert.isBoolean(quiet);
    }

    let forceStr = "";
    if (force) {
        forceStr = "-f";
    }

    const environ = Object.assign({}, process.env);
    // Hack: set a fake work-tree because the repo's core.worktree might
    // be set to a directory that, due to sparseness, doesn't exist, and
    // git push has a bug which requires it to have a worktree.
    environ.GIT_WORK_TREE = repo.path();

    const execString = `\
git -C '${repo.path()}' push ${forceStr} ${remote} ${source}:${target}`;
    try {
        const result = yield ChildProcess.exec(execString, {env : environ});
        if (result.error || !quiet) {
            if (result.stdout) {
                console.log(result.stdout);
            }
            if (result.stderr) {
                console.error(result.stderr);
            }
        }
        return null;
    }
    catch (e) {
        return e.message;
    }
});

/**
 * Return the name of the current branch in the specified `repo` or null if
 * there is no current branch.
 *
 * @param {NodeGit.Repository} repo
 */
exports.getCurrentBranchName = co.wrap(function *(repo) {
    assert.instanceOf(repo, NodeGit.Repository);

    if (!repo.isEmpty() && 1 !== repo.headDetached()) {
        let branch;
        try {
            branch = yield repo.getCurrentBranch();
        } catch (e) {
            // TODO: raise an issue with libgit2.  If your repository is in a
            // newly initialized state, but not fully empty (e.g., it has
            // configured remotes), this method throws an exception:
            // "reference 'refs/heads/master' not found".  Either it should
            // return null or `isEmpty` should return true.
            return null;
        }
        return branch.shorthand();
    }
    return null;
});

/**
 * Return the commit for the specified `commitish` in the specified `repo` or
 * null if `commitish` cannot be resolved.  Generally, `commitish` may be the
 * name of a branch or a partial commit SHA.
 *
 * @param {NodeGit.Repository} repo
 * @param {String}             commitish
 * @return {NodeGit.AnnotatedCommit|null}
 */
exports.resolveCommitish = co.wrap(function *(repo, commitish) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(commitish);

    try {
        return yield NodeGit.AnnotatedCommit.fromRevspec(repo, commitish);
    }
    catch (e) {
        return null;
    }
});

/**
 * Return a git note for the specified commit and ref, or null if the
 * commit has no note on that ref.
 *
 * @param {NodeGit.Repository} repo
 * @param {String}             notesRef
 * @param {String|NodeGit.Oid} oid
 * @return {NodeGit.Note|null}
 */
exports.readNote = co.wrap(function *(repo, notesRef, oid) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(notesRef);
    assert(typeof(oid) === "string" || oid instanceof NodeGit.Oid);

    try {
        return yield NodeGit.Note.read(repo, notesRef, oid);
    }
    catch (e) {
        return null;
    }
});

/**
 * Return a shortened version of the specified `sha`, or `sha` if it is already
 * short enough.
 *
 * @param {String} sha
 * @return {String}
 */
exports.shortSha = function (sha) {
    assert.isString(sha);
    return sha.substr(0, 6);
};

/**
 * Fetch the remote having the specified `remoteName in the specified `repo`.
 * Throw a `UserError` object if the repository cannot be fetched.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             remoteName
 */
exports.fetch = co.wrap(function *(repo, remoteName) {
    // TODO: this is an awful hack because I can't yet figure out how to get
    // nodegit to work with kerberos.  For now, will shell out and use the
    // 'git' command.

    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(remoteName);

    const execString = `git -C '${repo.path()}' fetch -q '${remoteName}'`;
    try {
        return yield ChildProcess.exec(execString);
    }
    catch (e) {
        throw new UserError(e.message);
    }
});

/**
 * Fetch the specified `branch` in the remote having the specified `remoteName
 * in the specified `repo`.  Throw a `UserError` object if the repository
 * cannot be fetched.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             remoteName
 * @param {String}             branch
 */
exports.fetchBranch = co.wrap(function *(repo, remoteName, branch) {
    // TODO: this is an awful hack because I can't yet figure out how to get
    // nodegit to work with kerberos.  For now, will shell out and use the
    // 'git' command.

    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(remoteName);
    assert.isString(branch);

    const execString = `\
git -C '${repo.path()}' fetch -q '${remoteName}' '${branch}'`;
    try {
        return yield ChildProcess.exec(execString);
    }
    catch (e) {
        throw new UserError(e.message);
    }
});

/**
 * Fetch the specified `sha` from the specified `url` into the specified
 * `repo`, if it does not already exist in `repo`; return true if a fetch
 * happened and false if the commit already existed in `repo`.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             url
 * @param {String}             sha
 * @return {Bool}
 */
exports.fetchSha  = co.wrap(function *(repo, url, sha) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(url);
    assert.isString(sha);

    // First, try to get the commit.  If we succeed, no need to fetch.

    try {
        yield repo.getCommit(sha);
        return false;                                                 // RETURN
    }
    catch (e) {
    }

    const execString = `git -C '${repo.path()}' fetch -q '${url}' ${sha}`;
    try {
        yield ChildProcess.exec(execString);
        yield repo.getCommit(sha);
    }
    catch (e) {
        throw new UserError(e.message);
    }
    return true;
});

/**
 * Return true if the specified `source` commit is up-to-date with the
 * specified `target` commit in the specified `repo`.  A commit is up-to-date
 * with `target` if it is the same commit, or if it is descended from `target`.
 *
 * @private
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             source
 * @param {String}             target
 * @return {Boolean}
 */
exports.isUpToDate = co.wrap(function *(repo, source, target) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(source);
    assert.isString(target);
    if (source === target) {
        return true;                                                  // RETURN
    }
    return yield NodeGit.Graph.descendantOf(repo, source, target);
});

/**
 * Set the HEAD of the specified `repo` to the specified `commit` and force the
 * contents to match it.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {NodeGit.Commit}     commit
 */
exports.setHeadHard = co.wrap(function *(repo, commit) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(commit, NodeGit.Commit);

    const headId = yield repo.getHeadCommit();
    let oldHead;
    if (headId === null) {
        oldHead = "0000000000000000000000000000000000000000";
    } else {
        oldHead = headId.id().tostrS();
    }
    const newHead = commit.sha();

    yield NodeGit.Checkout.tree(repo, commit, {
        checkoutStrategy: NodeGit.Checkout.STRATEGY.FORCE,
    });
    repo.setHeadDetached(commit);
    yield Hook.execHook(repo, "post-checkout", [oldHead, newHead, "1"]);
});

/**
 * @class {Refspec}
 *
 * This class represents the definition of a refspec.
 */
class Refspec {
    /**
     * Create a new `Refspec` object.
     *
     * @param {Boolean} force whether or not the refspec begins with +
     * @param {String} src
     * @param {String} dst
     * @constructor
     */
    constructor(force, src, dst) {
        assert.isBoolean(force);
        assert.isString(src);
        assert.isString(dst);
        this.d_force = force;
        this.d_src = src;
        this.d_dst = dst;
    }

    /**
     * @property {Boolean} update ref even if it isn't a fast-forward
     */
    get force() {
        return this.d_force;
    }

    /**
     * @property {String}
     */
    get src() {
        return this.d_src;
    }

    /**
     * @property {String}
     */
    get dst() {
        return this.d_dst;
    }
}

/**
 * Create a new `Refspec` object from a string.
 *
 * @param {String} str
 */
exports.parseRefspec = function(str) {
    assert.isString(str);

    let force = false;

    if (0 === str.indexOf("+")) {
        force = true;
        str = str.replace(/^\+/, "");
    }

    const objs = str.split(":");
    if (1 === objs.length) {
        return new Refspec(force, objs[0], objs[0]);
    }
    else if (2 === objs.length && "" !== objs[1]) {
        return new Refspec(force, objs[0], objs[1]);
    }

    throw new UserError("Refspec must match the format <src>:<dest>.");
};

/**
 * Resolve the specified `filename` against the specified `cwd` and return the
 * relative value for that resulting path to the specified `workdir`.  Throw a
 * `UserError` if the path lies outside `workdir` or does not refer to a file
 * in `workdir`.  Note that if `filename` resolves to `workdir`, the result is
 * `""`.
 *
 * @param {String} workdir
 * @param {String} cwd
 * @param {String} dir
 * @return {String}
 */
exports.resolveRelativePath = function (workdir, cwd, filename) {
    assert.isString(workdir);
    assert.isString(cwd);
    assert.isString(filename);

    const absPath = path.resolve(cwd, filename);
    const relPath = path.relative(workdir, absPath);
    if ("" !== relPath && "." === relPath[0]) {
        throw new UserError(`${colors.red(filename)} is outside the workdir.`);
    }
    return relPath;
};

/*
 * Return the editor command to use for the specified `repo`.
 *
 * @param {NodeGit.Repository} repo
 * @return {String}
 */
exports.getEditorCommand = co.wrap(function *(repo) {
    assert.instanceOf(repo, NodeGit.Repository);
    // TODO: libgit2 doesn't implement the equivalent of `git var` (or if it
    // does I can't see where), so rather than code this myself I shell out to
    // `git`.

    const result =
             yield ChildProcess.exec(`git -C '${repo.path()}' var GIT_EDITOR`);
    return result.stdout.split("\n")[0];
});

/**
 * Return the raw result of invoking the configured editor for the specified
 * `repo` with a file containing the specified `initialContents`.  Note that
 * the result may include `initialContents`; this method does not process the
 * result in any way.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             initialContents
 * @return {String}
 */
exports.editMessage = co.wrap(function *(repo, initialContents) {
    const messagePath = path.join(repo.path(), "COMMIT_EDITMSG");
    yield fs.writeFile(messagePath, initialContents);
    const editorCommand = yield exports.getEditorCommand(repo);

    // TODO: if we ever need this to work on Windows, we'll need to do
    // something else.  The `ChildProcess.exec` method doesn't provide for a
    // way to auto-redirect stdio or I'd use it.

    yield ChildProcess.spawn("/bin/sh",
                             ["-c", `${editorCommand} '${messagePath}'`], {
        stdio: "inherit",
    });
    return yield fs.readFile(messagePath, "utf8");
});

/**
 * Return true if the specified `line` is a comment and false otherwise.  A
 * line is a comment if the first non-whitespace character it contains is a
 * '#'.
 *
 * @param {String} line
 * @return {Boolean}
 */
exports.isComment = function (line) {
    assert.isString(line);
    return /^\s*#/.test(line);
};

/**
 * Return true if the specified `line` contains only whitespace characters and
 * false otherwise.
 *
 * @param {String} line
 * @return {Boolean
 */
exports.isBlank = function (line) {
    assert.isString(line);
    return /^\s*$/.test(line);
};

/**
 * Return the text contained in the specified array of `lines` after removing
 * all comment (i.e., those whose first non-whitespace character is a '#') and
 * leading and trailing blank (i.e., those containing only whitespace) lines.
 *
 * @param {String[]} lines
 * @return {String}
 */
exports.stripMessageLines = function (lines) {
    assert.isArray(lines);
    // First, remove all lines that are comments.

    const noComments = lines.filter(line => !exports.isComment(line));

    // Next, find the first and last lines in 'noComments' that contain
    // content, i.e., non-blank lines.

    let firstContent;
    let lastContent;
    for (let i = 0; i < noComments.length; ++i) {
        if (!exports.isBlank(noComments[i])) {
            firstContent =
                undefined === firstContent ? i : Math.min(i, firstContent);
            lastContent =
                undefined === lastContent ? i : Math.max(i, lastContent);
        }
    }
    if (undefined === firstContent) {
        return "";
    }

    // Now, return the result of splicing out the leading and trailing blank
    // lines.

    return noComments.slice(firstContent, lastContent + 1).join("\n") + "\n";
};

/**
 * Return the specified `message` with all comment lines removed (i.e., lines
 * where the first non-whitepsace character is a '#'), and all leading and
 * trailing blank (i.e., those containing only whitespace) lines removed.  Note
 * that any result that is not "" is terminated by a newline.
 *
 * @param {String} message
 * @return {String}
 */
exports.stripMessage = function (message) {
    assert.isString(message);
    const lines = message.split("\n");
    return exports.stripMessageLines(lines);
};

/**
 * Return the (left) parent `NodeGit.Commit` object for the specified `commit`
 * in the specified `repo`, or null if `commit` has no parent.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {NodeGit.Commit} commit
 * @return {NodeGit.Commit|null}
 */
exports.getParentCommit = co.wrap(function *(repo, commit) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(commit, NodeGit.Commit);
    if (0 === commit.parentcount()) {
        return null;                                                  // RETURN
    }
    const parentId = commit.parentId(0);
    return  yield repo.getCommit(parentId);
});

/**
 * Returns the URL for the specified remote.  If the remote is already
 * a URL, it is returned unmodified.
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String} remoteName
 * @return String
 * @throws if there's no such named remote
*/
exports.getUrlFromRemoteName = co.wrap(function *(repo, remoteName) {
    if (remoteName.startsWith("http:") || remoteName.startsWith("https:") ||
        remoteName.includes("@")) {
        return remoteName;
    } else {
        let remote;
        try {
            remote = yield repo.getRemote(remoteName);
        }
        catch (e) {
            throw new UserError(`No remote named ${colors.red(remoteName)}.`);
        }
        return yield exports.getRemoteUrl(repo, remote);
    }
});

/**
 * Return the merge base between the specifed `x` and `y` commits in the
 * specified `repo`, or null if there is no base.
 *
 *
 * @param {NodeGit.Repository} repo
 * @param {NodeGit.Commit}     x
 * @param {NodeGit.Commit}     y
 * @return {NodeGit.Commit|null}
 */
exports.getMergeBase = co.wrap(function *(repo, x, y) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(x, NodeGit.Commit);
    assert.instanceOf(y, NodeGit.Commit);

    let baseId;
    try {
        baseId = yield NodeGit.Merge.base(repo, x.id(), y.id());
    } catch (e) {
        // only way to detect lack of base
        return null;
    }
    return yield repo.getCommit(baseId);
});

/*
 * Update the HEAD of of the specified `repo` to point to the specified
 * `commit`.  If HEAD points to a branch, update that branch to point to
 * `commit` as well, and supply the specified `reason` for the reflog.
 *
 * @param {NodeGit.Repository} repo
 * @param {NodeGit.Commit}     commit
 * @param {String}             reason
 */
exports.updateHead = co.wrap(function *(repo, commit, reason) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(commit, NodeGit.Commit);
    assert.isString(reason);

    if (repo.headDetached()) {
        repo.setHeadDetached(commit.id());
    } else {
        const headRef = yield repo.head();
        yield headRef.setTarget(commit, reason);
    }
});

/*
 * Write the specified `data` to the specified `repo` and return its hash
 * value.
 *
 * @async
 * @private
 * @param {NodeGit.Repository} repo
 * @param {String}             data
 * @return {String}
 */
exports.hashObject = co.wrap(function *(repo, data) {
    const BLOB = 3;
    const db = yield repo.odb();
    const res = yield db.write(data, data.length, BLOB);
    return res;
});

/**
 * You would like to use NodeGit.Merge.bases, but unfortunately,
 * https://github.com/nodegit/nodegit/issues/1231
 * @async
 */
exports.mergeBases = co.wrap(function *(repo, commit1, commit2) {
    const id1 = commit1.id().tostrS();
    const id2 = commit2.id().tostrS();
    const execString = `\
git -C '${repo.path()}' merge-base ${id1} ${id2}`;
    const result = yield ChildProcess.exec(execString);
    if (result.error) {
        throw new UserError("Couldn't run git merge-base: " +
                            result.stderr);
    }
    return result.stdout.split("\n").filter(x => x);
});

/**
 * Return the `Reference` object having the specified `name` in the specified
 * `repo`, or null if no such reference exists.
 */
exports.getReference = co.wrap(function *(repo, name) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.isString(name);

    try {
        return yield NodeGit.Reference.lookup(repo, name);
    } catch (e) {
        // only way to tell `name` doesn't exist.
    }
    return null;
});


text:
// Type definitions for ember-resolver 4.5
// Project: https://github.com/ember-cli/ember-resolver#readme
// Definitions by: Dan Freeman <https://github.com/dfreeman>
//                 Mike North <https://github.com/mike-north>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.4

import Ember from 'ember';

/**
 * An Ember `Resolver` implementation used by ember-cli.
 */
export default class EmberResolver extends Ember.Resolver {}

redpajama_set_name: RedPajamaGithub


text:
package org.sleuthkit.autopsy.keywordsearch;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskException;

/**
 * AbstractFile input string stream reader/converter - given AbstractFile,
 * extract strings from it and return encoded bytes via read()
 *
 * Note: the utility supports extraction of only LATIN script and UTF8, UTF16LE, UTF16BE encodings
 * and uses a brute force encoding detection - it's fast but could apply multiple encodings on the same string.
 *
 * For other script/languages support and better encoding detection use AbstractFileStringIntStream streaming class,
 * which wraps around StringExtract extractor.
 */
 class AbstractFileStringStream extends InputStream {

    //args
    private AbstractFile content;
    private Charset outputCharset;
    //internal data
    private static final Logger logger = Logger.getLogger(AbstractFileStringStream.class.getName());
    private static final String NLS = Character.toString((char) 10); //new line
    private static final int READ_BUF_SIZE = 256;
    private long contentOffset = 0; //offset in fscontent read into curReadBuf
    private final byte[] curReadBuf = new byte[READ_BUF_SIZE];
    private int bytesInReadBuf = 0;
    private int readBufOffset = 0; //offset in read buf processed
    private StringBuilder curString = new StringBuilder();
    private int curStringLen = 0;
    private StringBuilder tempString = new StringBuilder();
    private int tempStringLen = 0;
    private boolean isEOF = false;
    private boolean stringAtTempBoundary = false; //if temp has part of string that didn't make it in previous read()
    private boolean stringAtBufBoundary = false; //if read buffer has string being processed, continue as string from prev read() in next read()
    private boolean inString = false; //if current temp has min chars required
    private final byte[] oneCharBuf = new byte[1];
    private final int MIN_PRINTABLE_CHARS = 4; //num. of chars needed to qualify as a char string

    /**
     * Construct new string stream from FsContent
     *
     * @param content to extract strings from
     * @param outputCharset target encoding to index as
     * @param preserveOnBuffBoundary whether to preserve or split string on a
     * buffer boundary. If false, will pack into read buffer up to max.
     * possible, potentially splitting a string. If false, the string will be
     * preserved for next read.
     */
    public AbstractFileStringStream(AbstractFile content, Charset outputCharset, boolean preserveOnBuffBoundary) {
        this.content = content;
        this.outputCharset = outputCharset;
        //this.preserveOnBuffBoundary = preserveOnBuffBoundary;
        //logger.log(Level.INFO, "FILE: " + content.getParentPath() + "/" + content.getName());
    }

    /**
     * Construct new string stream from FsContent Do not attempt to fill entire
     * read buffer if that would break a string
     *
     * @param content to extract strings from
     * @param outCharset target charset to encode into bytes and index as, e.g. UTF-8
     */
    public AbstractFileStringStream(AbstractFile content, Charset outCharset) {
        this(content, outCharset, false);
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        long fileSize = content.getSize();
        if (fileSize == 0) {
            return -1;
        }

        if (isEOF) {
            return -1;
        }

        if (stringAtTempBoundary) {
            //append entire temp string residual from previous read()
            //because qualified string was broken down into 2 parts
            appendResetTemp();

            stringAtTempBoundary = false;
            //there could be more to this string in fscontent/buffer
        }

        boolean singleConsecZero = false; //preserve the current sequence of chars if 1 consecutive zero char
        int newCurLen = curStringLen + tempStringLen;

        while (newCurLen < len) {
            //need to extract more strings
            if (readBufOffset > bytesInReadBuf - 1) {
                //no more bytes to process into strings, read them
                try {
                    bytesInReadBuf = 0;
                    bytesInReadBuf = content.read(curReadBuf, contentOffset, READ_BUF_SIZE);
                } catch (TskException ex) {
                    if (curStringLen > 0 || tempStringLen >= MIN_PRINTABLE_CHARS) {
                        appendResetTemp();
                        //have some extracted string, return that, and fail next time
                        isEOF = true;
                        int copied = copyToReturn(b, off, len);
                        return copied;
                    } else {
                        return -1; //EOF
                    }
                }
                if (bytesInReadBuf < 1) {
                    if (curStringLen > 0 || tempStringLen >= MIN_PRINTABLE_CHARS) {
                        appendResetTemp();
                        //have some extracted string, return that, and fail next time
                        isEOF = true;
                        int copied = copyToReturn(b, off, len);
                        return copied;
                    } else {
                        return -1; //EOF
                    }
                }
                //increment content offset for next read
                contentOffset += bytesInReadBuf;
                //reset read buf position
                readBufOffset = 0;
            }
            //get char from cur read buf
            char c = (char) curReadBuf[readBufOffset++];
            if (c == 0 && singleConsecZero == false) {
                //preserve the current sequence if max consec. 1 zero char
                singleConsecZero = true;
            } else {
                singleConsecZero = false;
            }
            if (StringExtract.isPrintableAscii(c)) {
                tempString.append(c);
                ++tempStringLen;
                if (tempStringLen >= MIN_PRINTABLE_CHARS) {
                    inString = true;
                }

                //boundary case when temp has still chars - handled after the loop
            } else if (!singleConsecZero) {
                //break the string, clear temp
                if (tempStringLen >= MIN_PRINTABLE_CHARS
                        || stringAtBufBoundary) {
                    //append entire temp string with new line
                    tempString.append(NLS);
                    ++tempStringLen;

                    curString.append(tempString);
                    curStringLen += tempStringLen;

                    stringAtBufBoundary = false;
                }
                //reset temp
                tempString = new StringBuilder();
                tempStringLen = 0;
            }

            newCurLen = curStringLen + tempStringLen;
        }

        //check if still in string state, so that next chars in read buf bypass min chars check
        //and qualify as string even if less < min chars required
        if (inString) {
            inString = false; //reset
            stringAtBufBoundary = true; //will bypass the check
        }

        //check if temp still has chars to qualify as a string
        //we might need to break up temp into 2 parts for next read() call
        //consume as many as possible to fill entire user buffer
        if (tempStringLen >= MIN_PRINTABLE_CHARS) {
            if (newCurLen > len) {
                int appendChars = len - curStringLen;
                //save part for next user read(), need to break up temp string
                //do not append new line
                String toAppend = tempString.substring(0, appendChars);
                String newTemp = tempString.substring(appendChars);

                curString.append(toAppend);
                curStringLen += appendChars;

                tempString = new StringBuilder(newTemp);
                tempStringLen = newTemp.length();

                stringAtTempBoundary = true;

            } else {
                //append entire temp
                curString.append(tempString);
                curStringLen += tempStringLen;

                //reset temp
                tempString = new StringBuilder();
                tempStringLen = 0;

            }
        } else {
            //if temp has a few chars, not qualified as string for now,
            //will be processed during next read() call
        }

        //copy current strings to user
        final int copied = copyToReturn(b, off, len);
        //there may be still chars in read buffer or  tempString, for next read()

        return copied;
    }

    //append temp buffer to cur string buffer and reset temp, if enough chars
    //does not append new line
    private void appendResetTemp() {
        if (tempStringLen >= MIN_PRINTABLE_CHARS) {
            curString.append(tempString);
            curStringLen += tempStringLen;
            tempString = new StringBuilder();
            tempStringLen = 0;
        }
    }

    //copy currently extracted string to user buffer
    //and reset for next read() call
    private int copyToReturn(byte[] b, int off, long len) {

        final String curStringS = curString.toString();
        //logger.log(Level.INFO, curStringS);
        byte[] stringBytes = curStringS.getBytes(outputCharset);
        System.arraycopy(stringBytes, 0, b, off, Math.min(curStringLen, (int) len));
        //logger.log(Level.INFO, curStringS);
        //copied all string, reset
        curString = new StringBuilder();
        int ret = curStringLen;
        curStringLen = 0;
        return ret;

    }

    @Override
    public int read() throws IOException {
        final int read = read(oneCharBuf, 0, 1);
        if (read == 1) {
            return oneCharBuf[0];
        } else {
            return -1;
        }

    }

    @Override
    public int available() throws IOException {
        //we don't know how many bytes in curReadBuf may end up as strings
        return 0;
    }

    @Override
    public long skip(long n) throws IOException {
        //use default implementation that reads into skip buffer
        //but it could be more efficient
        return super.skip(n);
    }
}


text:
angular.module('totalTesting').factory("Question", ["$http", function TestFactory($http) {
  var basePath = "/rest/v1/questions/";
    return {
      create: function(question) {
        return $http({method: "POST", url: basePath, data: question});
      },
      update: function(question) {
        return $http({method: "PUT", url: basePath + question.id, data: question});
      },
      deleteQuestion: function(questionId) {
        return $http({method: "Delete", url: basePath + questionId});
      },
      getByTest: function(testId) {
        return $http({method: "GET", url: "/rest/v1/tests/" + testId + "/questions"});
      },
      getRandom: function(number) {
        return $http({method: "GET", url: "/rest/v1/questions/random/" + number});
      }
    };
}]);


text:
<?php

namespace Inversion\Exception;

class InvalidNumberOfArguments extends Exception {

}


text:
<?xml version="1.0" encoding="utf-8"?>
<phpunit>
    <php>
   <!-- "Real" test database -->
        <var name="db_type" value="pdo_pgsql"/>
        <var name="db_host" value="localhost" />
        <var name="db_username" value="postgres" />
        <var name="db_password" value="" />
        <var name="db_name" value="doctrine_tests" />
        <var name="db_port" value="5432"/>
   <!--<var name="db_event_subscribers" value="Doctrine\DBAL\Event\Listeners\OracleSessionInit">-->

   <!-- Database for temporary connections (i.e. to drop/create the main database) -->
        <var name="tmpdb_type" value="pdo_pgsql"/>
        <var name="tmpdb_host" value="localhost" />
        <var name="tmpdb_username" value="postgres" />
        <var name="tmpdb_password" value="" />
        <var name="tmpdb_name" value="doctrine_tests_tmp" />
        <var name="tmpdb_port" value="5432"/>
    </php>

    <logging>
        <log type="coverage-clover" target="../../build/logs/clover.xml"/>
    </logging>

    <testsuites>
        <testsuite name="Doctrine ORM Test Suite">
            <directory>./../Doctrine/Tests/ORM</directory>
        </testsuite>
    </testsuites>

    <groups>
        <exclude>
            <group>performance</group>
            <group>locking_functional</group>
        </exclude>
    </groups>

</phpunit>


text:
date: 2015-02-23
layout: post
published: true
title: Deployment is Unix
url: /2015/02/23/deployment-is-unix.html
---

Over the last 3 years I've worked a lot on [Etsy's deployment
system][deployinator] (we've recently [brought the Open Source version back
into sync with our internal changes][deployinator_post] and are running on the
public version now as well). It's at the core of our development process as
all development is framed in the context of continuously deploying small
changes to the website. And the process of putting in feature flags and always
comitting to master follows from that. Deployinator is a Sinatra/Ruby
application that executes Bash scripts and commands in the background. It has
two buttons - for staging and production - that run the (shell) commands to
execute a list of deployment tasks. The usual tasks include refreshing the git
checkout on the build box, building/minifying JavaScript and CSS, compiling
templates, and rsyncing code to all the web servers (with our [atomic
deploys][atomic_deploys] there is also some symlink flipping involved). But
that's it, it's a very simple concept.

[![deployinator - ruby in the front, bash in the
back](/images/deployinator-ruby-bash.png)][talk]

Of course the overall application has a lot of features. And they keep growing
and changing as we figure out how a growing engineering team is using it. As
we have remediation items coming from PostMortems. And as more teams need and
add more deployment stacks for slightly different applications. The original
version of deployinator had an execution model where all commands where
executed in a streaming manner within an HTTP request. That meant we had to
configure the correct output buffering, had a long running request doing the
work and generally a somewhat confusing scenario where we often weren't sure
what would happen when you close your laptop lid in the middle of a deploy. We
also started to run into problems where the deploy would often break with SSH
broken pipe errors (all commands are run over ssh) in the middle of a run. We
tracked it down to an oddity in TCP behaviour between modern versions of OSX
and Linux.  And we decided that it was time to move the deploy run out of the
HTTP request. We thought about different ways of doing that and prototyped a
couple of things. And then one day while working on one of the prototypes of
the new deployment model I took a step back and realized that I was basically
trying to [reimplement OS process management in Ruby][unixtweet]. And this was
not what I wanted Deployinator to be. Deployinator is **UNIX**. So a
deployment is now done by [forking into a separate process][fork], setting the
process title to the stack and stage name and letting it run. `ps`, `kill`,
`nice` all still work. If you need to log into the deployment server and
figure things out, you can still use the tools you use every day. The rest of
Deployinator also always has been very UNIX inspired. The deployment process
runs commands over ssh and distributes commands to multiple machines via
[dsh][dsh]. All deployment output is written to a log file. The log file is
tailed by a websocket server to present it back to the web application. The
log in the web app shows all output of what the shell commands are doing. If
the commands write to STDERR, Deployinator shows it in red and bubbles it up
to a separate error log. This means you can write your deployment commands in
the well known UNIX style. Infos go to STDOUT, errors go to STDERR. In
addition Deployinator also comes with a command line tool to kick off any
deploy without needing a working web server.

And in my opinion this is how it should be. The actual steps of how your
software gets deployed will always be a little different. You might run a
Rails app instead of a PHP application. You might have a compiled binary that
needs to be shipped or you will have to restart services. You might git pull
on the servers directly instead of rsyncing files over. But there is always
the operating system as the common denominator (or almost always). And by
using that foundation in your tooling you already have a common ground when it
comes to understanding and debugging what your deployment system does. And
there are a lot of existing tools, like rsync, git or ssh which you can reuse
and leverage. There is also a [great response][gh_deploy] by [Corey][corey]
about how the GitHub deployment system works. And the final paragraph there
is really what I love most about it:

> I think people would be underwhelmed by the technology and implementation though. It's just a bit of ruby, UNIX, and HTTP. It's not pushing the boundaries of computing, it just chugs along doing its job so we don't have to.

And it really doesn't have to be complicated. Deployment can start with a
simple shell script. And then you can wrap it in a web frontend. Or an IRC
command.  Or an iPhone app. But at its core it's still manipulating files and
putting them on a computer. Deployment is still UNIX.

[deployinator_post]: https://codeascraft.com/2015/02/20/re-introducing-deployinator-now-as-a-gem/
[deployinator]: https://github.com/etsy/deployinator
[talk]: https://speakerdeck.com/mrtazz/the-road-to-success-is-paved-with-small-improvements?slide=68
[atomic_deploys]: https://codeascraft.com/2013/07/01/atomic-deploys-at-etsy/
[fork]: https://github.com/etsy/deployinator/blob/master/lib/deployinator/app.rb#L183
[unixtweet]: https://twitter.com/mrtazz/statuses/380547968174415872
[gh_deploy]: https://gist.github.com/atmos/6631554
[corey]: https://twitter.com/atmos
[dsh]: https://www.netfort.gr.jp/~dancer/software/dsh.html.en


text:
import unittest2 as unittest

from webkitpy.common.config.committers import Committer
from webkitpy.common.system.filesystem_mock import MockFileSystem
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.layout_tests.models import test_results
from webkitpy.layout_tests.models import test_failures
from webkitpy.thirdparty.mock import Mock
from webkitpy.tool.bot.flakytestreporter import FlakyTestReporter
from webkitpy.tool.mocktool import MockTool
from webkitpy.common.net.statusserver_mock import MockStatusServer

# Creating fake CommitInfos is a pain, so we use a mock one here.
class MockCommitInfo(object):
    def __init__(self, author_email):
        self._author_email = author_email

    def author(self):
        # It's definitely possible to have commits with authors who
        # are not in our contributors.json list.
        if not self._author_email:
            return None
        return Committer("Mock Committer", self._author_email)

class FlakyTestReporterTest(unittest.TestCase):
    def _mock_test_result(self, testname):
        return test_results.TestResult(testname, [test_failures.FailureTextMismatch()])

    def _assert_emails_for_test(self, emails):
        tool = MockTool()
        reporter = FlakyTestReporter(tool, 'dummy-queue')
        commit_infos = [MockCommitInfo(email) for email in emails]
        tool.checkout().recent_commit_infos_for_files = lambda paths: set(commit_infos)
        self.assertEqual(reporter._author_emails_for_test([]), set(emails))

    def test_author_emails_for_test(self):
        self._assert_emails_for_test([])
        self._assert_emails_for_test(["test1@test.com", "test1@test.com"])
        self._assert_emails_for_test(["test1@test.com", "test2@test.com"])

    def test_create_bug_for_flaky_test(self):
        reporter = FlakyTestReporter(MockTool(), 'dummy-queue')
        expected_logs = """MOCK create_bug
bug_title: Flaky Test: foo/bar.html
bug_description: This is an automatically generated bug from the dummy-queue.
foo/bar.html has been flaky on the dummy-queue.

foo/bar.html was authored by test@test.com.
http://trac.webkit.org/browser/trunk/LayoutTests/foo/bar.html

FLAKE_MESSAGE

The bots will update this with information from each new failure.

If you believe this bug to be fixed or invalid, feel free to close.  The bots will re-open if the flake re-occurs.

If you would like to track this test fix with another bug, please close this bug as a duplicate.  The bots will follow the duplicate chain when making future comments.

component: Tools / Tests
cc: test@test.com
blocked: 50856
"""
        OutputCapture().assert_outputs(self, reporter._create_bug_for_flaky_test, ['foo/bar.html', ['test@test.com'], 'FLAKE_MESSAGE'], expected_logs=expected_logs)

    def test_follow_duplicate_chain(self):
        tool = MockTool()
        reporter = FlakyTestReporter(tool, 'dummy-queue')
        bug = tool.bugs.fetch_bug(50004)
        self.assertEqual(reporter._follow_duplicate_chain(bug).id(), 50002)

    def test_report_flaky_tests_creating_bug(self):
        tool = MockTool()
        tool.filesystem = MockFileSystem({"/mock-results/foo/bar-diffs.txt": "mock"})
        tool.status_server = MockStatusServer(bot_id="mock-bot-id")
        reporter = FlakyTestReporter(tool, 'dummy-queue')
        reporter._lookup_bug_for_flaky_test = lambda bug_id: None
        patch = tool.bugs.fetch_attachment(10000)
        expected_logs = """Bug does not already exist for foo/bar.html, creating.
MOCK create_bug
bug_title: Flaky Test: foo/bar.html
bug_description: This is an automatically generated bug from the dummy-queue.
foo/bar.html has been flaky on the dummy-queue.

foo/bar.html was authored by abarth@webkit.org.
http://trac.webkit.org/browser/trunk/LayoutTests/foo/bar.html

The dummy-queue just saw foo/bar.html flake (text diff) while processing attachment 10000 on bug 50000.
Bot: mock-bot-id  Port: MockPort  Platform: MockPlatform 1.0

The bots will update this with information from each new failure.

If you believe this bug to be fixed or invalid, feel free to close.  The bots will re-open if the flake re-occurs.

If you would like to track this test fix with another bug, please close this bug as a duplicate.  The bots will follow the duplicate chain when making future comments.

component: Tools / Tests
cc: abarth@webkit.org
blocked: 50856
MOCK add_attachment_to_bug: bug_id=60001, description=Failure diff from mock-bot-id filename=failure.diff mimetype=None
MOCK bug comment: bug_id=50000, cc=None
--- Begin comment ---
The dummy-queue encountered the following flaky tests while processing attachment 10000:

foo/bar.html bug 60001 (author: abarth@webkit.org)
The dummy-queue is continuing to process your patch.
--- End comment ---

"""
        test_results = [self._mock_test_result('foo/bar.html')]

        class MockZipFile(object):
            def read(self, path):
                return ""

            def namelist(self):
                return ['foo/bar-diffs.txt']

        OutputCapture().assert_outputs(self, reporter.report_flaky_tests, [patch, test_results, MockZipFile()], expected_logs=expected_logs)

    def test_optional_author_string(self):
        reporter = FlakyTestReporter(MockTool(), 'dummy-queue')
        self.assertEqual(reporter._optional_author_string([]), "")
        self.assertEqual(reporter._optional_author_string(["foo@bar.com"]), " (author: foo@bar.com)")
        self.assertEqual(reporter._optional_author_string(["a@b.com", "b@b.com"]), " (authors: a@b.com and b@b.com)")

    def test_results_diff_path_for_test(self):
        reporter = FlakyTestReporter(MockTool(), 'dummy-queue')
        self.assertEqual(reporter._results_diff_path_for_test("test.html"), "test-diffs.txt")

    def test_find_in_archive(self):
        reporter = FlakyTestReporter(MockTool(), 'dummy-queue')

        class MockZipFile(object):
            def namelist(self):
                return ["tmp/layout-test-results/foo/bar-diffs.txt"]

        reporter._find_in_archive("foo/bar-diffs.txt", MockZipFile())
        # This is not ideal, but its
        reporter._find_in_archive("txt", MockZipFile())


text:
from django.conf.urls import patterns, include, url
from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin

urlpatterns = patterns('',
    url(r'^', include('todo.urls')),
    url(r'^api/', include('todo.api')),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^djangojs/', include('djangojs.urls')),
) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)


text:
package gitbase

import (
	"io"
	"os"

	"gopkg.in/src-d/go-errors.v1"
	"gopkg.in/src-d/go-git.v4/plumbing/object"
	"gopkg.in/src-d/go-git.v4/plumbing/storer"
	"gopkg.in/src-d/go-git.v4/storage/filesystem"
	"gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit"
	"gopkg.in/src-d/go-git.v4/utils/ioutil"

	sivafs "gopkg.in/src-d/go-billy-siva.v4"
	"gopkg.in/src-d/go-billy.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/format/idxfile"
	"gopkg.in/src-d/go-git.v4/plumbing/format/objfile"
	"gopkg.in/src-d/go-git.v4/plumbing/format/packfile"
)

func repositoryPackfiles(fs billy.Filesystem) (*dotgit.DotGit, []plumbing.Hash, error) {
	fs, err := findDotGit(fs)
	if err != nil {
		return nil, nil, err
	}

	dot := dotgit.New(fs)
	packfiles, err := dot.ObjectPacks()
	if err != nil {
		return nil, nil, err
	}

	return dot, packfiles, nil
}

type packfileIndex struct {
	packfile plumbing.Hash
	idx      idxfile.Index
}

type repositoryIndex struct {
	dir       *dotgit.DotGit
	indexes   []*packfileIndex
	closeFunc func()
}

func newRepositoryIndex(repo *Repository) (*repositoryIndex, error) {
	fs, err := repo.FS()
	if err != nil {
		return nil, err
	}

	var closeFunc func()
	if s, ok := fs.(sivafs.SivaSync); ok {
		closeFunc = func() { s.Sync() }
	}

	dot, packfiles, err := repositoryPackfiles(fs)
	if err != nil {
		return nil, err
	}

	ri := &repositoryIndex{dir: dot, closeFunc: closeFunc}
	for _, p := range packfiles {
		idx, err := openPackfileIndex(dot, p)
		if err != nil {
			return nil, err
		}

		ri.indexes = append(ri.indexes, &packfileIndex{p, idx})
	}

	return ri, nil
}

func openPackfileIndex(
	dotGit *dotgit.DotGit,
	hash plumbing.Hash,
) (*idxfile.MemoryIndex, error) {
	f, err := dotGit.ObjectPackIdx(hash)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	idx := idxfile.NewMemoryIndex()
	if err := idxfile.NewDecoder(f).Decode(idx); err != nil {
		return nil, err
	}

	return idx, nil
}

var errHashNotInIndex = errors.NewKind("object hash %s is not in repository")

func (i *repositoryIndex) find(hash plumbing.Hash) (int64, plumbing.Hash, error) {
	for _, idx := range i.indexes {
		ofs, err := idx.idx.FindOffset(hash)
		if err == plumbing.ErrObjectNotFound {
			continue
		}

		if err != nil {
			return 0, plumbing.ZeroHash, err
		}

		return ofs, idx.packfile, nil
	}

	ok, err := i.isUnpacked(hash)
	if err != nil || ok {
		return -1, plumbing.ZeroHash, err
	}

	return -1, plumbing.ZeroHash, errHashNotInIndex.New(hash)
}

func (i *repositoryIndex) isUnpacked(hash plumbing.Hash) (bool, error) {
	f, err := i.dir.Object(hash)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}

		return false, err
	}
	if err := f.Close(); err != nil {
		return false, err
	}

	return true, nil
}

func (i *repositoryIndex) Close() {
	if i.closeFunc != nil {
		i.closeFunc()
	}
}

func findDotGit(fs billy.Filesystem) (billy.Filesystem, error) {
	fi, err := fs.Stat(".git")
	if err != nil && !os.IsNotExist(err) {
		return nil, err
	}

	if fi != nil && fi.IsDir() {
		return fs.Chroot(".git")
	}

	return fs, nil
}

func getUnpackedObject(repo *Repository, hash plumbing.Hash) (o object.Object, err error) {
	fs, err := repo.FS()
	if err != nil {
		return nil, err
	}

	fs, err = findDotGit(fs)
	if err != nil {
		return nil, err
	}

	dot := dotgit.New(fs)

	f, err := dot.Object(hash)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, plumbing.ErrObjectNotFound
		}

		return nil, err
	}

	defer ioutil.CheckClose(f, &err)

	storage := filesystem.NewStorage(fs, repo.Cache())

	obj := storage.NewEncodedObject()
	r, err := objfile.NewReader(f)
	if err != nil {
		return nil, err
	}

	defer ioutil.CheckClose(r, &err)

	t, size, err := r.Header()
	if err != nil {
		return nil, err
	}

	obj.SetType(t)
	obj.SetSize(size)
	w, err := obj.Writer()
	if err != nil {
		return nil, err
	}

	_, err = io.Copy(w, r)

	o, err = object.DecodeObject(storage, obj)
	return
}

type repoObjectDecoder struct {
	repo      string
	hash      plumbing.Hash
	packfile  *packfile.Packfile
	storage   storer.EncodedObjectStorer
	closeFunc func()
}

func newRepoObjectDecoder(
	repo *Repository,
	hash plumbing.Hash,
) (*repoObjectDecoder, error) {
	fs, err := repo.FS()
	if err != nil {
		return nil, err
	}

	var closeFunc func()
	if f, ok := fs.(sivafs.SivaSync); ok {
		closeFunc = func() { f.Sync() }
	}

	fs, err = findDotGit(fs)
	if err != nil {
		return nil, err
	}

	dot := dotgit.New(fs)
	packf, err := dot.ObjectPack(hash)
	if err != nil {
		return nil, err
	}

	storage := filesystem.NewStorage(fs, repo.Cache())

	idx, err := openPackfileIndex(dot, hash)
	if err != nil {
		return nil, err
	}

	packfile := packfile.NewPackfile(idx, fs, packf)

	return &repoObjectDecoder{
		repo:      repo.ID(),
		hash:      hash,
		packfile:  packfile,
		storage:   storage,
		closeFunc: closeFunc,
	}, nil
}

func (d *repoObjectDecoder) equals(repo string, hash plumbing.Hash) bool {
	return d.repo == repo && d.hash == hash
}

func (d *repoObjectDecoder) get(offset int64) (object.Object, error) {
	encodedObj, err := d.packfile.GetByOffset(offset)
	if err != nil {
		return nil, err
	}

	return object.DecodeObject(d.storage, encodedObj)
}

func (d *repoObjectDecoder) Close() error {
	if d.closeFunc != nil {
		d.closeFunc()
	}

	return d.packfile.Close()
}

type objectDecoder struct {
	pool    *RepositoryPool
	decoder *repoObjectDecoder
}

func newObjectDecoder(pool *RepositoryPool) *objectDecoder {
	return &objectDecoder{pool: pool}
}

func (d *objectDecoder) decode(
	repository string,
	packfile plumbing.Hash,
	offset int64,
	hash plumbing.Hash,
) (object.Object, error) {
	repo, err := d.pool.GetRepo(repository)
	if err != nil {
		return nil, err
	}

	if offset >= 0 {
		if d.decoder == nil || !d.decoder.equals(repository, packfile) {
			if d.decoder != nil {
				if err := d.decoder.Close(); err != nil {
					return nil, err
				}
			}

			var err error
			d.decoder, err = newRepoObjectDecoder(repo, packfile)
			if err != nil {
				return nil, err
			}
		}

		return d.decoder.get(offset)
	}

	return getUnpackedObject(repo, hash)
}

func (d *objectDecoder) Close() error {
	if d.decoder != nil {
		return d.decoder.Close()
	}

	return nil
}


text:
package org.gameoss.gridcast.p2p;

import org.gameoss.gridcast.p2p.discovery.NodeDiscovery;
import org.gameoss.gridcast.p2p.listener.ClusterListener;
import org.gameoss.gridcast.p2p.message.JoinRequest;
import org.gameoss.gridcast.p2p.message.JoinResponse;
import org.gameoss.gridcast.p2p.message.MessageRegistry;
import org.gameoss.gridcast.p2p.message.MessageWrapper;
import org.gameoss.gridcast.p2p.node.*;
import org.gameoss.gridcast.p2p.util.Net;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.nio.NioEventLoopGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * NodeRepository maintains a list of Gridcast peer-to-peer connections.
 */
public class ClusterClient {
    private final static Logger logger = LoggerFactory.getLogger(ClusterClient.class);

    private final Node localNode;
    private final NodeServer server;
    private final MessageRegistry messageRegistry = new MessageRegistry();
    private final ScheduledExecutorService executorService;
    private final ScheduledFuture<?> pollingTask;
    private final NioEventLoopGroup bossGroup;
    private final NioEventLoopGroup workerGroup;
    private final Object joinLock = new Object();

    private final AtomicInteger nodeCount = new AtomicInteger(0);
    private final Map<NodeId,Node> idToNode = new ConcurrentHashMap<>();
    private final Map<NodeAddress,Node> addrToNode = new ConcurrentHashMap<>();

    private NodeDiscovery discovery;
    private ClusterListener listener;

    public ClusterClient(ClusterListener listener, String hostAddress, int hostPort, NodeDiscovery discovery, long msPollingTime, ScheduledExecutorService executorService) {
        this.listener = listener;
        this.discovery = discovery;
        this.executorService = executorService;
        this.bossGroup = new NioEventLoopGroup();
        this.workerGroup = new NioEventLoopGroup();

        // create local node
        NodeAddress localAddr;
        if (hostAddress != null && !hostAddress.isEmpty()) {
            localAddr = new NodeAddress(hostAddress,hostPort);
        } else {
            localAddr = new NodeAddress(Net.getLocalAddress(), hostPort );
        }
        localNode = new LocalNode(this, new NodeId(),localAddr);
        addNode(localNode);

        // Create listener for peer connections
        server = new NodeServer();
        server.initialize(hostAddress, hostPort, bossGroup, workerGroup, messageRegistry, new ServerChannelHandler());

        // schedule polling task
        pollingTask = executorService.scheduleWithFixedDelay( new Runnable() {
            @Override
            public void run() {
                pollForNodes();
            }
        }, 0, msPollingTime, TimeUnit.MILLISECONDS);
    }

    /**
     * Get the message registry for this client
     * @return message registry
     */
    public MessageRegistry getMessageRegistry() {
        return messageRegistry;
    }

    /**
     * Send message to the destination node.
     * @param destinationNodeId
     * @param msg
     */
    public void sendMessage(NodeId destinationNodeId, Object msg) {
        Node node = idToNode.get(destinationNodeId);
        if (node != null) {
            MessageWrapper wrapper = MessageWrapper.wrap(msg);
            node.sendMessage(wrapper);
            wrapper.release();
        }
    }

    /**
     * Send message to the destination nodes
     * @param destinationNodeIds
     * @param msg
     */
    public void sendMessage(List<NodeId> destinationNodeIds, Object msg) {
        MessageWrapper wrapper = MessageWrapper.wrap(msg);
        for (NodeId nid : destinationNodeIds) {
            Node node = idToNode.get(nid);
            if (node != null) {
                node.sendMessage( wrapper );
            }
        }
        wrapper.release();
    }

    /**
     * Send message to all nodes.
     * @param msg
     */
    public void sendMessageToAll(Object msg, boolean includeSelf) {
        MessageWrapper wrapper = MessageWrapper.wrap(msg);
        for (Node node : idToNode.values()) {
            if (!includeSelf && node == localNode) {
                continue;
            }
            node.sendMessage(wrapper);
        }
        wrapper.release();
    }

    /**
     * Get the local node's id.
     * @return local node id
     */
    public NodeId getLocalNodeId() {
        return localNode.getId();
    }

    /**
     * Get number of nodes in the peer-to-peer network.
     * @return
     */
    public int getNodeCount() {
        return nodeCount.get();
    }

    /**
     * Get the cluster listener
     */
    public ClusterListener getClusterListener() {
        return listener;
    }

    /**
     * Shutdown this node of the peer-to-peer network.
     */
    public void shutdown() {
        pollingTask.cancel(false);
        server.shutdown();
        for (Node node : idToNode.values()) {
            node.close();
        }
        idToNode.clear();
        addrToNode.clear();
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();

        // break dependencies
        listener = null;
        discovery = null;
    }

    /**
     * Use the NodeProvider to poll for Gridcast peers.
     */
    private void pollForNodes() {
        try {
            for (NodeAddress address : discovery.getNodeAddresses()) {
                synchronized (joinLock) {
                    if (addrToNode.containsKey(address)) {
                        continue;
                    }
                    Node node = new RemoteNode(this,address,workerGroup,messageRegistry,localNode);
                    addNode(node);
                }
            }
        } catch (Exception ex) {
            logger.error("Unexpected exception polling for nodes", ex);
        }
    }

    /**
     * Add node to repository.
     * @param node
     */
    public void addNode(final Node node) {
        Node existingNode = null;
        synchronized (joinLock) {
            if (node.getId() != null) {
                existingNode = idToNode.put(node.getId(), node);
            }
            if (node.getAddress() != null) {
                addrToNode.put(node.getAddress(),node);
            }
        }
        if (existingNode == null && node.getId() != null) {
            nodeCount.incrementAndGet();
            executorService.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            listener.onNodeJoin(ClusterClient.this, node.getId());
                        }
                    });
        }
    }

    /**
     * Remove node from repository.
     * @param node
     */
    public void removeNode(final Node node) {
        Node existingNode = null;
        synchronized (joinLock) {
            if (node.getId() != null) {
                existingNode = idToNode.remove(node.getId());
            }
            if (node.getAddress() != null) {
                addrToNode.remove(node.getAddress());
            }
        }
        if (existingNode != null) {
            nodeCount.decrementAndGet();
            executorService.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            listener.onNodeLeft(ClusterClient.this, node.getId());
                        }
                    });
        }
    }

    /**
     * Handle initial join message from incoming peers and hand off to node
     */
    @ChannelHandler.Sharable
    private class ServerChannelHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof JoinRequest) {
                JoinRequest joinRequest = (JoinRequest) msg;

                // Check for duplicate IDs in the peer network.  Rare but could happen.
                if (joinRequest.getJoinerId() == localNode.getId()) {
                    logger.error("Duplicate ID found in the peer network");
                    ctx.writeAndFlush(new JoinResponse(JoinResponse.ResponseCode.REJECTED_ID_ALREADY_IN_USE,localNode.getId(), localNode.getAddress()));
                    ctx.close();
                    return;
                }

                // Handle join request
                synchronized (joinLock) {
                    if (joinRequest.getJoinerAddress().equals(localNode.getAddress())) {
                        logger.error("Received join for myself?  Shouldn't happen.");
                        return;
                    }

                    Node existingNode = addrToNode.get(joinRequest.getJoinerAddress());
                    if (existingNode != null) {
                        if (existingNode.getId() != null) {
                            // we already have an active node to that client, reject this join
                            ctx.writeAndFlush(new JoinResponse(JoinResponse.ResponseCode.REJECTED_EXISTING_CONNECTION, localNode.getId(), localNode.getAddress()));
                            return;
                        } else if (localNode.getId().compareTo(joinRequest.getJoinerId()) < 0) {
                            // our node is still initializing but our Id is lower so reject the join
                            ctx.writeAndFlush(new JoinResponse(JoinResponse.ResponseCode.REJECTED_EXISTING_CONNECTION, localNode.getId(), localNode.getAddress()));
                            return;
                        } else {
                            // our node is still initializing but our Id is higher so kill ours and allow join
                            existingNode.setAbandoned(true);
                            idToNode.remove(joinRequest.getJoinerId());
                            addrToNode.remove(joinRequest.getJoinerAddress());
                        }
                    } else {
                        // unknown node, so continue join process
                    }

                    // add new node for this connection
                    Node newNode = new RemoteNode(ClusterClient.this, joinRequest.getJoinerId(), joinRequest.getJoinerAddress(), ctx.channel(), this);
                    addNode(newNode);
                }

                // notify incoming connection they are good
                ctx.writeAndFlush(new JoinResponse(JoinResponse.ResponseCode.OK, localNode.getId(), localNode.getAddress()));
            } else {
                logger.error("Unexpected message in ServerChannelHandler: ", msg.getClass().toString());
            }
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            logger.error("Exception processing message", cause);
        }
    }
}


text:
<META http-equiv="content-type" content="text/html;charset=iso-8859-9"/><meta name="viewport" content="width=device-width, initial-scale=1"><title>ac</title> <link rel="stylesheet"  href="css/jquery.mobile-1.2.0.css" />

CELAL TEHANÝSERÝ

Geri

Hindistan'da yetiþen velilerden. Doðum tarihi belli deðildir. Aslen Belhlidir. Babasýnýn ismi
Kadý Mahmud'dur. Anne ve baba tarafýndan hazret-i Ömer'e dayanýr. 1581 (H.989) senesinde
vefat etti. Vefat ettiðinde doksan beþ yaþýný geçmiþti. Kabri, doðum yeri olan Tehaniser'dedir.

Celal Tehaniseri küçük yaþta ilim tahsiline baþladý. Yedi yaþýnda Kur'an-ý kerimi ezberledi.
On yedi yaþýna geldiðinde bütün ilimleri öðrenip ders ve fetva vermeye baþladý. Bir gün hoþ
bir ses ile okunan gazeli duydu. O anda kendisini Allahü tealanýn aþký kapladýðýndan düþüp
bayýldý. Ayýldýðýnda tasavvuf yolunu öðrenmek için Abdülkuddus hazretlerinin sohbetlerine
devam etti. Kýsa zamanda kemale gelerek icazet, diploma aldý.

Celal Tehaniseri, ilmi ile amil idi. Ömrünü ibadet, taat, ders vermek ve insanlara vaz ve
nasihat etmekle geçirdi. Edepleri gözetmeye, farzlardan baþka nafileleri yapmaya,
gece-gündüz Allahü tealayý zikretmeye ve vakitlerini deðerlendirmeye çok dikkat ederdi.
Çoðunlukla Allahü tealanýn aþký ile kendinden geçmiþ bir halde olurdu. Namaz vakti gelince
talebeleri; "Allahü ekber, Allahü ekber." dediðinde kendine gelir, namazý kýlmak için
kalkardý.

Celal Tehaniseri'nin ölüm hastalýðý, sekerat hali günlerce uzadý. Bu sebepten bir þaþkýnlýk ve
ýzdýrap hasýl oldu. On altý gün sonra kendine gelince, talebelerinin büyüklerinden olan Þeyh
Nizam bu hale üzüldüðü için; "Efendim, bu ne haldir?" diye sorunca, Celal Tehaniseri
coþarak þu beyti okudu:

Vücudundan fani olan kimseler,
Harften suretten, manaya geçerler.

Talebelerine þöyle buyururdu: "Aþýklar, keþf ve keramet konaklarýnda durmak istemesinler.
Daha yukarýlara çýksýnlar. Hiçbir þeye baðlý kalmasýnlar. Her þeyden kesilerek ve
uzaklaþarak, can çýkarcasýna ilerlesinler. Bu da þöyle olur; ibadetlere, zühde; dünyaya düþkün
olmamaya ve riyazete, nefsin isteklerine uymamaya dikkat etsinler. Bunlarý vesile bilsinler.
Az yemek yesinler, hatta can çýkýncaya kadar uðraþsýnlar. Ölmeden evvel ölüp, nefslerini tam
ýslah edip, Hakk'a kavuþsunlar. Kendini tasavvuf yolunda sananlar ve cahil sufiler (cahil
tarikatçýlar) bu hususta hataya düþüyor ve doðru yoldan çýkýyorlar. Bundan Allahü tealaya
sýðýnýrýz. Selef-i salihinden (radýyallahü anhüm ecmain) rivayet edildi ki: "Usulsüz vüsul,
kavuþma olmaz. Usul; dinin emirlerine ve tasavvufta bulunduðu yola uymaktýr." Kur'an-ý
kerim okumak ve din ilimleriyle meþgul olmak en iyi iþtir."

HERKESÝN KALDIRACAK GÜCÜ YOKTUR
Celal Tehaniseri'nin talebelerinden birisi, birkaç sene onun sohbetlerinde bulunmasýna raðmen, onda
hiçbir manevi hal görülmemiþti. Bir gün Celal Tehaniseri'nin sohbetinde bulunan bu talebe, kendi
kendine; "Þeyh Necmeddin-i Kübra öyle bir zat idi ki, nazar ettiði kimse evliyalýk mertebesine
kavuþurdu. Bugün böyle bir zat yok." diye aklýndan geçirdi. Celal Tehaniseri onun bu düþüncesine,
Allahü tealanýn izni ile vakýf oldu. Onun bulunduðu tarafa bakarak; "Bugün de öyleleri vardýr."
buyurup, bir kere ona baktýlar. Talebe o anda evliyalýk mertebesine kavuþtu ve kendinden geçti.
Evliyalýkta en yüksek dereceye kavuþan talebe, kýsa bir süre sonra vefat etti. Bunun üzerine Celal
Tehaniseri; "Herkesin bu iþi kaldýracak gücü yoktur." buyurdu.

1) Zübdet-ül-Makamat (Berekat-ý Ahmediyye); s.103

2) Umdet-ül-Makamat; s.111

3) Sefinet-ül-Evliya; s.101

4) Müntehab-üt-Tevarih; c.3, s.3

5) Sevafi-ul-Envar; s.31

6) Hazinet-ül-Asfiya; c.1, s.439

7) Ahbar-ül-Ahyar; s.291

8) Persian Literature; c.1, s.17


text:
#ifndef itkMinMaxCurvatureFlowFunction_h
#define itkMinMaxCurvatureFlowFunction_h

#include "itkCurvatureFlowFunction.h"
#include "itkNeighborhoodOperator.h"

namespace itk
{
/** \class MinMaxCurvatureFlowFunction
 *
 * This class encapsulate the finite difference equation which drives a
 * min/max curvature flow denoising algorithm.
 *
 * This class uses a zero flux Neumann boundary condition when computing
 * derivatives near the data boundary.
 *
 * This class operates as part of the finite difference solver hierarchy.
 *
 * \sa MinMaxCurvatureFlowImageFilter
 * \sa ZeroFluxNeumannBoundaryCondition
 * \ingroup FiniteDifferenceFunctions
 * \ingroup ITKCurvatureFlow
 */
template< typename TImage >
class ITK_TEMPLATE_EXPORT MinMaxCurvatureFlowFunction:
  public CurvatureFlowFunction< TImage >
{
public:
  /**  Standard class typedefs. */
  typedef MinMaxCurvatureFlowFunction     Self;
  typedef CurvatureFlowFunction< TImage > Superclass;
  typedef SmartPointer< Self >            Pointer;
  typedef SmartPointer< const Self >      ConstPointer;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

  /** Run-time type information (and related methods) */
  itkTypeMacro(MinMaxCurvatureFlowFunction,
               CurvatureFlowFunction);

  /** Inherit some parameters from the superclass type. */
  typedef typename Superclass::ImageType        ImageType;
  typedef typename Superclass::PixelType        PixelType;
  typedef typename Superclass::RadiusType       RadiusType;
  typedef typename Superclass::NeighborhoodType NeighborhoodType;
  typedef typename Superclass::FloatOffsetType  FloatOffsetType;

  /** Extract superclass dimension. */
  itkStaticConstMacro(ImageDimension, unsigned int,
                      Superclass::ImageDimension);

  /** Typedef support for the stencil radius. */
  typedef typename RadiusType::SizeValueType RadiusValueType;

  /** Set/Get the stencil radius. */
  void SetStencilRadius(const RadiusValueType radius);

  const RadiusValueType & GetRadiusValueType() const
  { return m_StencilRadius; }

  /** Convenience function for symmetry with SetStencilRadius. */
  const RadiusValueType & GetStencilRadius() const
  { return GetRadiusValueType(); }

  /** This method computes the solution update for each pixel that does not
   * lie on a the data set boundary. */
  virtual PixelType ComputeUpdate(const NeighborhoodType & neighborhood,
                                  void *globalData,
                                  const FloatOffsetType & offset = FloatOffsetType(0.0)
                                  ) ITK_OVERRIDE;

protected:
  MinMaxCurvatureFlowFunction();
  ~MinMaxCurvatureFlowFunction() {}

  typedef Neighborhood< PixelType, itkGetStaticConstMacro(ImageDimension) > StencilOperatorType;
  StencilOperatorType m_StencilOperator;

  /** Initialize the stencil opearator to be an N-Dimensional sphere
   * of radius m_StencilRadius. */
  void InitializeStencilOperator();

private:
  ITK_DISALLOW_COPY_AND_ASSIGN(MinMaxCurvatureFlowFunction);

  RadiusValueType m_StencilRadius;

  // To control overloaded versions of ComputeThreshold
  struct DispatchBase {};
  template< signed int VDimension >
  struct Dispatch: public DispatchBase {};

  /** This method computes the threshold by averaging the intensity
   *  in direction perpendicular to the image gradient. */
  PixelType ComputeThreshold(const Dispatch< 2 > &,
                             const NeighborhoodType & neighborhood) const;

  PixelType ComputeThreshold(const Dispatch< 3 > &,
                             const NeighborhoodType & neighborhood) const;

  PixelType ComputeThreshold(const DispatchBase &,
                             const NeighborhoodType & neighborhood) const;
};
} // end namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
#include "itkMinMaxCurvatureFlowFunction.hxx"
#endif

#endif


text:
- Drop python 3.6, add python 3.11 (@hugovk - thx)

## 6.1.2

- Reintroduce the cli options

## 6.1.1

- Remove type hinting (temporarily)

## 6.1.0

- Add `allow_unicode` flag to allow unicode characters in the slug

## 6.0.1

- Rework regex_pattern to mean the opposite (disallowed chars instead of allowed)
- Thanks to @yyyyyyyan for the initial PR followed by the final PR by @mrezzamoradi

## 6.0.0

- Enable github action
- Remove tox, as we run the test on github action, the end users can refer to those test

## 5.0.2

- Enable twine publish

## 5.0.1

- Drop support for python 2.7, 3.5 & tox, clean up

## 5.0.0

- Add support for Py 3.9 - added tox (@jon-betts - Thx)
- Drop support for python 2.7, 3.5 & friends

## 4.0.1

- Add support for Py 3.8
- Last version with `official` python 2.7 and <= 3.5 support

## 4.0.0

- Drop support from 2.6, & < 3.4.5

## 3.0.6

- Fixed encoding in special.py

## 3.0.5

- Add test for pre-translation (e.g German Umlaut)
- Add special char supports (optional Use)

## 3.0.4

- Now supporting text-unidecode>=1.3
- Now supporting Unidecode>=1.1.1

## 3.0.3

- Remove unicode chars from file

## 3.0.2

- Add official support of Py 3.7

## 3.0.1

- Add test.py to manifest

## 3.0.0

- Upgrade Unidecode
- Promote text-unidecode as the primary decoding package
- Add Unidecode as an optional extra. "pip install python-slugify[unidecode]"

## 2.0.1

- Add replacements option e.g. [['|', 'or'], ['%', 'percent'], ['-', '_']] (@andriyor)

## 2.0.0

- Fix alternative dependency installation

## 1.2.6

- Add support for case sensitive slugs (@s-m-e)

## 1.2.5

- Add support for using text-unidecode (@bolkedebruin)
- Switch to pycodestyle instead of pep8

## 1.2.4

- Remove build artifacts during packaging
- Simplify the setup.py file (@reece)

## 1.2.3

- Republish - possible corrupt 1.2.2 build

## 1.2.2

- Add `regex_pattern` option. (@vrbaskiz)
- Add Python 3.6 support

## 1.2.1

- Including certain files (e.g. license.md) in sdists via MANIFEST.in (@proinsias)
- Relax licensing by moving from BSD to MIT
- Add Python 3.5 support
- Add more tests

## 1.2.0

Backward incompatible change: (@fabiocaccamo)

- In version < 1.2.0 all single quotes ( ' ) were removed, and
  moving forward, >= 1.2.0, they will be replaced with ( - ).
  Example:
  < 1.2.0 -- ('C\'est déjà l\'été.' -> "cest-deja-lete")
  > = 1.2.0 -- ('C\'est déjà l\'été.' -> "c-est-deja-l-ete")

## 1.1.4

Bugfix:

- Add more test cases, dropped `official` support for python 3.2

## 1.1.3

Bugfix:

- Handle unichar in python 3.x

## 1.1.2

Enhancement:

- Ability to remove `stopwords` from string

## 1.0.2

Enhancement:

- A new PyPI release

## 1.0.1

Enhancement:

- Promoting to production grade

## 0.1.1

Enhancement:

- Added option to save word order
- Removed 2to3 dependency
- Added more tests

## 0.1.0

Enhancement:

- Added more test
- Added test for python 3.4

## 0.0.9

Enhancement:

- Enable console_scripts

## 0.0.8

Enhancement:

- Move logic out of **init**.py
- Added console_scripts (@ekamil)
- Updated pep8.sh
- Added pypy support

## 0.0.7

Enhancement:

- Handle encoding in setup file
- Update ReadME, ChangeLog, License files

## 0.0.6

Enhancement:

- Update for smart_truncate

## 0.0.5

Features:

- Added Python 3.2 and 3.3 support (work by: arthurdarcet@github)

## 0.0.4

Features:

- Added option to choose non-dash separators (request by: danilodimoia@github)

## 0.0.3

Features:

- Added the ability to truncate slugs (request by: juanriaza@github)

## 0.0.2

Enhancement:

- Incremental update

## 0.0.1

- Initial version


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>All Classes</title>
<meta name="date" content="2016-02-27">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">

All Classes

PixelController

PixelController.Screen


text:
* Every totem file consists of a single class or single interface.
* Each totem file name must be identical to the class or interface that file contains.
* The core totem library should be written in C or Python.
* We will then write a standard library in totem, building on the core.

## The core totem library

* Should contain the Object class.
* Should contain the following classes (or something like them), directly inheriting from Object:
* Array
* Numeric
* Exception
* InputOutput
* Hash
* Random
* Range
* String
* Structure (or maybe leave out)
* Thread
* Time

* Object should contain methods for the following tasks:
* cloning the object
* checking equality
* getting rid of the object when not referenced
* returning class of the object
* setting / getting hashcode for object
* providing string representation of the object

## The standard totem library

## totem keywords

* class
* new
* for
* in
* return
* private
* public
* packaged
* this
* inherits


text:
      ForceFeed

    <submitterList (SelectionChanged)='onSubmitterSelectionChanged( $event )'></submitterList>

                Changelists will not be automatically refreshed while any changelist is expanded.

              {{ _paginationText }}

        <changelist [data]='changelistData'></changelist>

          {{ _paginationText }}


text:
from __future__ import division, print_function
import os
import re

import nbformat as nbf
from nbconvert.nbconvertapp import NbConvertApp

################################################################################
### Making report notebooks

def make_notebook(out_name, fname, key, n, level=.1, kernel_name=None):
    v = nbf.v4
    nb = v.new_notebook()
    if kernel_name is not None:
        from jupyter_client.kernelspec import KernelSpecManager
        d = KernelSpecManager().get_kernel_spec(kernel_name).to_dict()
        nb['metadata']['kernelspec'] = {
            'name': kernel_name,
            'display_name': d['display_name'],
        }
        nb['metadata']['language_info'] = {
            'name': d['language'],
        }

    add_code = lambda s: nb['cells'].append(v.new_code_cell(s.strip()))
    add_markdown = lambda s: nb['cells'].append(v.new_markdown_cell(s.strip()))

    add_code(r'''
from __future__ import division, print_function
from operator import itemgetter
import os

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

import numpy as np
import pandas as pd
import statsmodels.api as sm

from scipy.stats.mstats import mquantiles
from scipy import stats
''')

    add_code(r'''
probs = (.025, .16, .5, .84, .975)
def plot_band(group, probs=probs, ax=None, **kwargs):
    if ax is None:
        from matplotlib import pyplot as ax
    x = np.asarray([k for k, v in group])
    assert np.all(np.diff(x) > 0)
    bits = group.apply(lambda y: stats.mstats.mquantiles(y, prob=probs))
    get = lambda i: bits.apply(itemgetter(i))
    ax.fill_between(x, get(0), get(-1), alpha=.2, **kwargs)
    ax.fill_between(x, get(1), get(-2), alpha=.2, **kwargs)
    ax.plot(x, get(2))
''')

    add_code(r'''
basedir = {!r}
fname = {!r}
key = {!r}
n = {!r}
level = {!r}
'''.format(os.path.abspath(os.path.dirname(__file__)), fname, key, n, level))

    add_markdown('## Load data')
    add_code(r'''
# load data
d = pd.read_hdf(os.path.join(basedir, fname), key)
if 'samps' in d:
    d['samps'] = d.samps.map(lambda x: np.fromstring(x, dtype=np.float32))
''')

    add_code(r'''
# basic info
sigmas = d.index.get_level_values('sigma').unique()
assert np.all(np.diff(sigmas) > 0)

n_reps = len(d.index.get_level_values('rep').unique())
''')

    add_markdown("Estimate the power for each bandwidth by the number of "
                 "successes across repetitions:")
    add_code(r'''
n_succ = d.groupby(level='sigma').p.agg(lambda x: (x <= level).sum())
power = n_succ / n_reps
''')

    add_code(r'''
m = 'jeffrey'
lo1, hi1 = sm.stats.proportion_confint(n_succ, n_reps, alpha=.32, method=m)
lo2, hi2 = sm.stats.proportion_confint(n_succ, n_reps, alpha=.05, method=m)

plt.xscale('log')
plt.fill_between(sigmas, lo2, hi2, alpha=.2)
plt.fill_between(sigmas, lo1, hi1, alpha=.2)
plt.plot(sigmas, power)
plt.ylim(0, 1)
''')

    add_code(r'''
def add_power(ax=None, **kwargs):
    if ax is None:
        ax = plt.gca()
    kwargs.setdefault('color', 'k')
    kwargs.setdefault('ls', '--')
    kwargs.setdefault('alpha', .5)

    xlim = ax.get_xlim()
    ax2 = ax.twinx()
    ax2.plot(sigmas, power, **kwargs)
    ax2.grid(False)
    ax2.set_yticks([], [])
    ax2.set_ylim(0, 1)
    ax2.set_xlim(*xlim)
''')

    add_markdown("## Computing criteria")
    add_code(r'''
d['ratio'] = d.mmd_est / np.sqrt(d.var_est)
if 'thresh_{}'.format(level) in d:
    d['thresh'] = d['thresh_{}'.format(level)]
elif 'samps' in d:
    d['thresh'] = d.samps.map(lambda s: mquantiles(s, prob=1 - level)[0])
else:
    raise ValueError("Sorry, can't do level {}. Could do any of {}".format(
        level, ', '.join(str(float(k[len('thresh_'):]))
                         for k in d if k.startswith('thresh_'))))
d['criterion'] = -(d.thresh / (n * np.sqrt(d.var_est)) - d.ratio)
''')

    add_code(r'''
plt.xscale('log')
plot_band(d.mmd_est.groupby(level=0))
plt.title(r'MMD$^2$ estimates')
add_power()
''')

#     add_code(r'''
# plt.xscale('log')
# plot_band(d.var_est.apply(np.sqrt).groupby(level=0))
# plt.title(r'$\sqrt{\text{Var}}$ estimates')
# add_power()
# ''')

    add_code(r'''
plt.xscale('log')
plot_band(d.ratio.groupby(level=0))
plt.title(r'$\mathrm{MMD}^2 / \sqrt{\mathrm{Var}}$ estimates')
add_power()
''')

    add_code(r'''
plt.xscale('log')
plot_band(d.criterion.groupby(level=0))
plt.title(r'$-(\frac{c_\alpha}{n \sqrt{\mathrm{Var}}} - '
          r'\frac{\mathrm{MMD}^2}{\sqrt{\mathrm{Var}}})$ estimates')
add_power()
''')

    add_markdown(r"## Maximizing estimates")
    add_code(r'''
max_sigmas = d[['mmd_est', 'ratio', 'criterion']].groupby(level='rep').agg(lambda x: x.idxmax()[0])
max_powers = max_sigmas.apply(lambda x: power.loc[x].values)
''')

    add_markdown(r"Selected bandwidths by each method:")
    add_code(r'''
for i, (k, color) in enumerate([('mmd_est', 'b'), ('ratio', 'r'), ('criterion', 'g')], 1):
    ax = plt.subplot(3, 1, i)

    for s in sigmas:
        ax.axvline(s, color='w')

    vc = max_sigmas[k].value_counts().loc[sigmas].fillna(0)
    for s, c in vc.iteritems():
        c = int(c)
        ax.plot([s] * c, np.arange(c),
                 marker='o', ls='', color=color)

    ax.set_xscale('log')
    ax.grid(False)
    ax.set_yticks([], [])
    ax.set_xlim(sigmas[0] / 1.1, sigmas[-1] * 1.1)
    ax.set_ylim(-1, vc.max())
    ax.set_title(k)
    add_power(ax)
plt.tight_layout()
#**chosen_sigmas_stacked** <- keep this tag for get_plots
''')

    add_code(r'''
plt.xscale('log')
xs = np.linspace(np.log10(sigmas[0]) - .1, np.log10(sigmas[-1]) + .1, 50)
for k in max_sigmas.columns:
    kde = stats.gaussian_kde(max_sigmas[k].apply(np.log10))
    plt.plot(10 ** xs, kde(xs), label=k)
plt.legend()

add_power()
#**chosen_sigmas_kde** <- keep this tag for get_plots
''')

    add_markdown(r"Powers of the bandwidths selected by each method:")
    add_code(r'''
a = np.array(max_powers).T
a += np.random.uniform(-1e-6, 1e-6, size=a.shape)  # jitter so KDE still works
sm.graphics.beanplot(a, labels=max_powers.columns, jitter=True)

mx = power.max()
plt.axhline(mx, color='k', alpha=.5)
plt.ylim(0, min(1, mx + .05, mx * 1.1))
#**power_beanplots** <- keep this tag for get_plots
''')

    with open(out_name, 'w') as f:
        nbf.write(nb, f)

def main():
    import argparse
    parser = argparse.ArgumentParser(description='''
        Make (and run) a jupyter notebook visualizing the results of an output
        file from fixed_run.py.'''.strip())
    parser.add_argument('fname')
    parser.add_argument('--key', default='df')
    parser.add_argument('out_name', nargs='?')
    parser.add_argument('-n', type=int)
    parser.add_argument('--level', type=float, default=.1)
    parser.add_argument('--kernel-name')
    parser.add_argument('--force', '-f', action='store_true')
    args = parser.parse_args()

    if args.out_name is None:
        assert args.fname.endswith('.h5')
        base = args.fname[:-3]
        args.out_name = base + '.ipynb'
    else:
        d = os.path.dirname(args.out_name)
        if d and not os.path.isdir(d):
            os.makedirs(d)

    if not args.force and os.path.exists(args.out_name):
        parser.exit("Output {} already exists; use --force to overwrite."
                    .format(args.out_name))
    del args.force

    if args.n is None:
        match = re.search('/n(\d+)\.h5$', args.fname)
        if match:
            args.n = int(match.group(1))
        else:
            parser.error('-n must be specified unless filename has it')

    make_notebook(**vars(args))
    nbc = NbConvertApp()
    nbc.initialize([
        '--to=notebook', '--execute',
        '--output', os.path.basename(args.out_name),
        args.out_name])
    nbc.convert_notebooks()

if __name__ == '__main__':
    main()


text:
<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
 <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.text" manifest:version="1.2" manifest:full-path="/"/>
 <manifest:file-entry manifest:media-type="image/jpeg" manifest:full-path="Pictures/10000000000004B000000384EBE1A25C.jpg"/>
 <manifest:file-entry manifest:media-type="image/jpeg" manifest:full-path="Pictures/10000000000004B0000003845995D8D9.jpg"/>
 <manifest:file-entry manifest:media-type="image/jpeg" manifest:full-path="Pictures/10000000000004B00000038407C4C7E5.jpg"/>
 <manifest:file-entry manifest:media-type="image/jpeg" manifest:full-path="Pictures/10000000000004B00000038427EE7D09.jpg"/>
 <manifest:file-entry manifest:media-type="image/jpeg" manifest:full-path="Pictures/10000000000004B00000038470B8DCFB.jpg"/>
 <manifest:file-entry manifest:media-type="image/jpeg" manifest:full-path="Pictures/10000000000004B000000384B6410D30.jpg"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Pictures/"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
 <manifest:file-entry manifest:media-type="application/binary" manifest:full-path="layout-cache"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/thumbnail.png"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/current.xml"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/progressbar/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/floater/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/popupmenu/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/menubar/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/toolbar/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/Bitmaps/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/"/>
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/statusbar/"/>
 <manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
</manifest:manifest>