summary refs log blame commit diff stats
path: root/test/tc_directory.py
blob: f1b204c3616c8e9a00d16a4764d823d7a85a2683 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                       
                                                            
 

                                           
                           

                                               


                                                
 

                                                      
                                              
 
               
                               
                                         
                                                          
                                        

                                                   

                                                     
                                                 
                                                                  
 
                                            
                         
                                                                                
                                        
                                  

                                           
                                                           
 


                                                                                       

                                                                                    

                                        

                                             




                                                                                 
                                      
                                
                                                 



                                                                                       
 
                                       
                
# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

if __name__ == '__main__': from __init__ import init; init()

from os.path import realpath, join, dirname

from ranger import fsobject
from ranger.fsobject.file import File
from ranger.fsobject.directory import Directory
from ranger.shared.settings import SettingsAware

SettingsAware._setup()

TESTDIR = realpath(join(dirname(__file__), 'testdir'))
TESTFILE = join(TESTDIR, 'testfile5234148')
NONEXISTANT_DIR = join(TESTDIR, 'nonexistant')

import unittest
class Test1(unittest.TestCase):
	def test_initial_condition(self):
		# Check for the expected initial condition
		dir = Directory(TESTDIR)

		self.assertEqual(dir.path, TESTDIR)
		self.assertFalse(dir.content_loaded)
		self.assertEqual(dir.filenames, None)
		self.assertEqual(dir.files, None)
		self.assertRaises(fsobject.NotLoadedYet, len, dir)

	def test_after_content_loaded(self):
		import os
		# Check whether the directory has the correct list of filenames.
		dir = Directory(TESTDIR)
		dir.load_content()

		self.assertTrue(dir.exists)
		self.assertEqual(type(dir.filenames), list)

		# Get the filenames you expect it to have and sort both before
		# comparing. I don't expect any order after only loading the filenames.
		assumed_filenames = os.listdir(TESTDIR)
		assumed_filenames = list(map(lambda str: os.path.join(TESTDIR, str),
			assumed_filenames))
		assumed_filenames.sort()
		dir.filenames.sort()

		self.assertTrue(len(dir) > 0)
		self.assertEqual(dir.filenames, assumed_filenames)

		# build a file object for each file in the list assumed_filenames
		# and find exactly one equivalent in dir.files
		for name in assumed_filenames:
			f = File(name)
			f.load()
			for dirfile in dir.files:
				if (f.path == dirfile.path and f.stat == dirfile.stat):
					break
			else:
				self.fail("couldn't find file {0}".format(name))

	def test_nonexistant_dir(self):
		dir = Directory(NONEXISTANT_DIR)
		dir.load_content()
		
		self.assertTrue(dir.content_loaded)
		self.assertFalse(dir.exists)
		self.assertFalse(dir.accessible)
		self.assertEqual(dir.filenames, None)
		self.assertRaises(fsobject.NotLoadedYet, len, dir)

	def test_load_if_outdated(self):
		import os
		import time
		# modify the directory. If the time between the last modification
		# was within the filesystems resolution of mtime, we should have a reload

		def modify_dir():
			open(TESTFILE, 'w').close()
			os.unlink(TESTFILE)

		def mtime():
			return os.stat(TESTDIR).st_mtime

		dir = Directory(TESTDIR)
		dir.load()

		# If the modification happens to be in the same second as the
		# last modification, it will result in mtime having the same
		# integer value. So we wait until the resolution is exceeded
		# and mtime differs.
		old_mtime = mtime()
		for i in range(50):
			modify_dir()
			if old_mtime != mtime(): break
			time.sleep(0.1)
		else:
			# fail after 5 seconds of trying
			self.fail(
					"Cannot perform test: mtime of TESTDIR is not being updated.")

		self.assertTrue(dir.load_if_outdated())

if __name__ == '__main__':
	unittest.main()
="k">interactive) (if (magit-toplevel) (let* ((branches (vc-git-branches)) (main-p (member "main" branches)) (current-branch (car branches)) (on-master-p (member current-branch '("master" "main"))) (command (concat "git " (if main-p "update-main" "update-master")))) (if on-master-p (vc-pull) (magit-shell-command-topdir command))) (message "Not a git repository"))) ;; difftastic code copied from https://tsdh.org/posts/2022-08-01-difftastic-diffing-with-magit.html (defun my/magit--with-difftastic (buffer command) "Run COMMAND with GIT_EXTERNAL_DIFF=difft then show result in BUFFER." (let ((process-environment (cons (concat "GIT_EXTERNAL_DIFF=difft --width=" (number-to-string (frame-width))) process-environment))) ;; Clear the result buffer (we might regenerate a diff, e.g., for ;; the current changes in our working directory). (with-current-buffer buffer (setq buffer-read-only nil) (erase-buffer)) ;; Now spawn a process calling the git COMMAND. (make-process :name (buffer-name buffer) :buffer buffer :command command ;; Don't query for running processes when emacs is quit. :noquery t ;; Show the result buffer once the process has finished. :sentinel (lambda (proc event) (when (eq (process-status proc) 'exit) (with-current-buffer (process-buffer proc) (goto-char (point-min)) (ansi-color-apply-on-region (point-min) (point-max)) (setq buffer-read-only t) (view-mode) (end-of-line) ;; difftastic diffs are usually 2-column side-by-side, ;; so ensure our window is wide enough. (let ((width (current-column))) (while (zerop (forward-line 1)) (end-of-line) (setq width (max (current-column) width))) ;; Add column size of fringes (setq width (+ width (fringe-columns 'left) (fringe-columns 'right))) (goto-char (point-min)) (pop-to-buffer (current-buffer) `(;; If the buffer is that wide that splitting the frame in ;; two side-by-side windows would result in less than ;; 80 columns left, ensure it's shown at the bottom. ,(when (> 80 (- (frame-width) width)) #'display-buffer-at-bottom) (window-width . ,(min width (frame-width)))))))))))) (defun my/magit-show-with-difftastic (rev) "Show the result of \"git show REV\" with GIT_EXTERNAL_DIFF=difft." (interactive (list (or ;; If REV is given, just use it. (when (boundp 'rev) rev) ;; If not invoked with prefix arg, try to guess the REV from ;; point's position. (and (not current-prefix-arg) (or (magit-thing-at-point 'git-revision t) (magit-branch-or-commit-at-point))) ;; Otherwise, query the user. (magit-read-branch-or-commit "Revision")))) (if (not rev) (error "No revision specified") (my/magit--with-difftastic (get-buffer-create (concat "*git show difftastic " rev "*")) (list "git" "--no-pager" "show" "--ext-diff" rev)))) (defun my/magit-diff-with-difftastic (arg) "Show the result of \"git diff ARG\" with GIT_EXTERNAL_DIFF=difft." (interactive (list (or ;; If RANGE is given, just use it. (when (boundp 'range) range) ;; If prefix arg is given, query the user. (and current-prefix-arg (magit-diff-read-range-or-commit "Range")) ;; Otherwise, auto-guess based on position of point, e.g., based on ;; if we are in the Staged or Unstaged section. (pcase (magit-diff--dwim) ('unmerged (error "unmerged is not yet implemented")) ('unstaged nil) ('staged "--cached") (`(stash . ,value) (error "stash is not yet implemented")) (`(commit . ,value) (format "%s^..%s" value value)) ((and range (pred stringp)) range) (_ (magit-diff-read-range-or-commit "Range/Commit")))))) (let ((name (concat "*git diff difftastic" (if arg (concat " " arg) "") "*"))) (my/magit--with-difftastic (get-buffer-create name) `("git" "--no-pager" "diff" "--ext-diff" ,@(when arg (list arg)))))) (require 'ansi-color) ;; https://tsdh.org/posts/2022-07-20-using-eldoc-with-magit-async.html ;; https://tsdh.org/posts/2021-06-21-using-eldoc-with-magit.html (defvar my/eldoc-git-show-stat--process nil) (defun my/eldoc-git-show-stat (callback commit) "Compute diffstat for COMMIT asynchronously, then call CALLBACK with it." ;; Kill the possibly still running old process and its buffer. (when (processp my/eldoc-git-show-stat--process) (let ((buf (process-buffer my/eldoc-git-show-stat--process))) (when (process-live-p my/eldoc-git-show-stat--process) (let (confirm-kill-processes) (kill-process my/eldoc-git-show-stat--process))) (when (buffer-live-p buf) (kill-buffer buf)))) ;; Spawn a new "git show" process. (let* ((cmd (list "git" "--no-pager" "show" "--no-color" ;; Author Name <author@email.com>, <date-and-time> "--format=format:%an <%ae>, %aD" "--stat=80" commit))) ;; An async eldoc-documentation-function must also return a non-nil, ;; non-string result if it's applicable for computing a documentation ;; string, so we set and return the new process here. (setq my/eldoc-git-show-stat--process (make-process :name "eldoc-git-show" :buffer (generate-new-buffer " *git-show-stat*") :noquery t :command cmd :sentinel (lambda (proc event) (when (eq (process-status proc) 'exit) (with-current-buffer (process-buffer proc) (goto-char (point-min)) (put-text-property (point-min) (line-end-position) 'face 'bold) (funcall callback (buffer-string))))))))) (defvar my/magit-eldoc-last-commit nil) (defun my/magit-eldoc-for-commit (callback) (let ((commit (magit-commit-at-point))) (when (and commit (not (equal commit my/magit-eldoc-last-commit))) (setq my/magit-eldoc-last-commit commit) (my/eldoc-git-show-stat callback commit)))) (defun my/magit-eldoc-setup () (add-hook 'eldoc-documentation-functions #'my/magit-eldoc-for-commit nil t)) (add-hook 'magit-status-mode-hook #'my/magit-eldoc-setup) (add-hook 'magit-log-mode-hook #'my/magit-eldoc-setup) (eldoc-add-command 'magit-next-line) (eldoc-add-command 'magit-previous-line) ;; Based on https://tsdh.org/posts/2022-08-01-difftastic-diffing-with-magit.html (transient-define-prefix my/magit-extra-commands () "Extra magit commands." ["Extra commands" ("u" "Set upstream" my/magit-set-upstream) ("r" "Refresh state (update modeline)" my/magit-refresh-state) ("m" "Update master/main" my/magit-update-master) ("d" "Difftastic Diff (dwim)" my/magit-diff-with-difftastic) ("s" "Difftastic Show" my/magit-show-with-difftastic) ("D" "Toggle magit-delta-mode" my/toggle-delta-mode)]) (transient-append-suffix 'magit-dispatch "!" '("#" "Extra Magit Cmds" my/magit-extra-commands)) (define-key magit-status-mode-map (kbd "#") #'my/magit-extra-commands) :custom (magit-diff-refine-hunk 'all) (magit-diff-paint-whitespace-lines 'all) (magit-diff-refine-ignore-whitespace nil) (magit-diff-highlight-trailing t)) (use-package magit-delta :after magit :demand t :config (defun my/toggle-delta-mode () (interactive) (call-interactively #'magit-delta-mode) (magit-refresh))) (use-package forge :after magit :bind (:map forge-pullreq-list-mode-map ("C-w" . forge-copy-url-at-point-as-kill))) (use-package git-link :config (defun git-link-on-branch () (interactive) (let ((git-link-use-commit nil)) (call-interactively 'git-link))) (defun git-link-branch () (interactive) (let* ((remote-info (git-link--parse-remote (git-link--remote-url (git-link--select-remote)))) (branch (git-link--branch))) (if (null (car remote-info)) (message "Remote `%s' contains an unsupported URL" remote) (git-link--new (format "https://%s/%s/tree/%s" (car remote-info) (cadr remote-info) branch))))) :custom (git-link-use-commit t) :bind ("C-c g s" . git-link) ("C-c g S" . git-link-on-branch) ("C-c g c" . git-link-commit) ("C-c g b" . git-link-branch)) (use-package git-related :straight nil :defer 10) (provide 'init-git) ;;; init-git.el ends here