conao3 / dired-git.el

Show git repository information in dired buffer
GNU General Public License v3.0
12 stars 3 forks source link

Doesn't work on Windows #9

Open mateialexandru opened 2 years ago

mateialexandru commented 2 years ago

Warning (emacs): Fail invoke git command buffer: # reason:(exited abnormally with code 255 FIND: Parameter format not correct 'tr' is not recognized as an internal or external command, operable program or batch file. )

jasonm23 commented 2 years ago

The core of the mode is this shell command, so it'll need to be re-created for Windows:

       "find . -mindepth 1 -maxdepth 1 -type d | sort | tr \\\\n \\\\0 | \
xargs -0 -I^ sh -c \"
cd ^
git rev-parse --is-inside-work-dir >/dev/null 2>&1 || exit 0
if [ \\\"true\\\" = \\\"\\$(git rev-parse --is-inside-git-dir)\\\" ]; then exit 0; fi
if [ \\\"\\$PWD\\\" != \\\"\\$(git rev-parse --show-toplevel)\\\" ]; then exit 0; fi
branch=\\\"\\$(git symbolic-ref --short HEAD)\\\"
remote=\\\"\\$(git config --get branch.\\${branch}.remote)\\\"

git rev-parse \\${remote}/\\${branch} >/dev/null 2>&1
if [ 0 -ne \\$? ]; then
  forward=\\\"-\\\"
  behind=\\\"-\\\"
else
  forward=\\\"\\$(git log \\${remote}/\\${branch}..\\${branch} --oneline | wc -l)\\\"
  behind=\\\"\\$(git log \\${branch}..\\${remote}/\\${branch} --oneline | wc -l)\\\"
fi

echo \\\"(\
 file \\\\\\\"\\$PWD\\\\\\\"\
 branch \\\\\\\"\\${branch}\\\\\\\"\
 remote \\\\\\\"\\${remote}\\\\\\\"\
 forward \\\\\\\"\\${forward}\\\\\\\"\
 behind \\\\\\\"\\${behind}\\\\\\\"\
)\\\"
\"
jasonm23 commented 2 years ago

For convenience, cleaned up with all the shonk removed.

find . -mindepth 1 -maxdepth 1 -type d \
| sort \
| tr '\n' '\0' \
| xargs -0 -I^ sh -c \
cd ^
git rev-parse --is-inside-work-dir >/dev/null 2>&1 || exit 0
if [ "true" = "$(git rev-parse --is-inside-git-dir)" ]; then exit 0; fi
if [ "$PWD" != "$(git rev-parse --show-toplevel)" ]; then exit 0; fi
branch="$(git symbolic-ref --short HEAD)"
remote="$(git config --get branch.${branch}.remote)"

git rev-parse ${remote}/${branch} >/dev/null 2>&1
if [ 0 -ne $? ]; then
  forward="-"
  behind="-"
else
  forward="$(git log ${remote}/${branch}..${branch} --oneline | wc -l)"
  behind="$(git log ${branch}..${remote}/${branch} --oneline | wc -l)"
fi

echo "(
 file "$PWD"
 branch "${branch}"
 remote "${remote}"
 forward "${forward}"
 behind "${behind}"
)"
jasonm23 commented 2 years ago

Probably best to just convert this to lisp.

Coming soon....
jasonm23 commented 2 years ago

Cross platform, find directories at dir...

(defun directories (dir)
  "List directories at DIR."
  (cl-reduce
     (lambda (dirs filename)
       "directories at pwd"
       (when (file-directory-p filename)
         (setq dirs (push filename dirs)))
       dirs)
   (cddr (directory-files dir t)) :initial-value '()))
jasonm23 commented 2 years ago
(defun git-branch-local ()
  "Return the local git branch at pwd.
Returns an empty string if we are not in a git work-tree."
  (if (eql 'w32 (window-system))
    (string-trim (shell-command-to-string "git symbolic-ref --short HEAD 2> nul")))
  (string-trim (shell-command-to-string "git symbolic-ref --short HEAD 2> /dev/null")))

(defun git-remote-for (local-branch)
  "Return the remote for LOCAL-BRANCH at pwd.
Returns an empty string if we are not in a git work-tree."
  (string-trim (shell-command-to-string (format "git config --get branch.%s.remote" local-branch))))

(git-remote-for "main")
jasonm23 commented 2 years ago
(defun git-top-level-p (dir)
  "Return non-nil if DIR is top-level of the work-tree."
  (string= dir
   (shell-command-to-string "git rev-parse --show-toplevel")))
jasonm23 commented 2 years ago
(defun directories (dir)
  "List directories at DIR."
  (cl-reduce
     (lambda (dirs filename)
       "directories at pwd"
       (when (file-directory-p filename)
         (setq dirs (push filename dirs)))
       dirs)
   (cddr (directory-files dir t)) :initial-value '()))

(directories default-directory)

(defun git-top-level-p (dir)
  "Return non-nil if DIR is top-level of the work-tree."
  (let ((top-level (string-chop-newline (shell-command-to-string "git rev-parse --show-toplevel"))))
   (string= (file-name-as-directory top-level)
            (file-name-as-directory dir))))

(git-top-level-p default-directory)

(defun redirect-stderr-to-null ()
  "Generate cross platform stderr redirect."
  (if (eql 'w32 (window-system))
     " 2> nul "
   " 2> /dev/null "))

(redirect-stderr-to-null)

(defun git-branch-local ()
  "Return the local git branch at pwd.
Returns an empty string if we are not in a git work-tree."
  (string-trim (shell-command-to-string (format "git symbolic-ref --short %s" (redirect-stderr-to-null)))))

(git-branch-local)

(defun git-remote-for (local-branch)
  "Return the remote for LOCAL-BRANCH at pwd.
Returns an empty string if we are not in a git work-tree."
  (string-trim (shell-command-to-string (format "git config --get branch.%s.remote %s" local-branch (redirect-stderr-to-null)))))

(git-remote-for "main")

(defun git-local-branch-ahead-of-remote (local-branch remote)
  "Return the number of commits LOCAL-BRANCH is ahead of REMOTE (or 0)."
  (let* ((log (shell-command-to-string (format "git log %2$s/%1$s..%1$s --oneline %3$s" local-branch remote (redirect-stderr-to-null))))
         (count (s-count-matches "\n" log)))
    count))

(cd "ayah")

(git-local-branch-ahead-of-remote "main" "origin")

(defun git-local-branch-behind-remote (local-branch remote)
  "Return the number of commits LOCAL-BRANCH is behind REMOTE (or 0)."
  (let* ((log (shell-command-to-string (format "git log %1$s..%2$s/%1$s --oneline %3$s" local-branch remote (redirect-stderr-to-null))))
         (count (s-count-matches "\n" log)))
    count))

(git-local-branch-behind-remote "main" "origin")

Ok throw these into *scratch* and see if they work as expected on Windows... I don't have access to a Windows machine.

jasonm23 commented 2 years ago

use (cd "c:\a-git-repo-you-have\") and (cd "c:\") (or however that's supposed to work.) to check the behavior when in and out of a repo.

I'm sure we can make this thing cross platform.