Removed elpa
This commit is contained in:
		@@ -1,447 +0,0 @@
 | 
			
		||||
(1
 | 
			
		||||
 (load-relative .
 | 
			
		||||
		[(0 1)
 | 
			
		||||
		 nil "relative file load (within a multi-file Emacs package)" single])
 | 
			
		||||
 (test-unit .
 | 
			
		||||
	    [(0 1)
 | 
			
		||||
	     nil "Unit Test Framework for Emacs Lisp " single])
 | 
			
		||||
 (zenburn .
 | 
			
		||||
	  [(1 8)
 | 
			
		||||
	   nil "just some alien fruit salad to keep you in the zone" single])
 | 
			
		||||
 (multi-project .
 | 
			
		||||
		[(0 0 1)
 | 
			
		||||
		 nil "Work with multiple projects" single])
 | 
			
		||||
 (hungry-delete .
 | 
			
		||||
		[(1 0)
 | 
			
		||||
		 nil "hungry delete minor mode" single])
 | 
			
		||||
 (Save-visited-files .
 | 
			
		||||
		     [(1 2)
 | 
			
		||||
		      nil "save opened files across sessions" single])
 | 
			
		||||
 (c-eldoc .
 | 
			
		||||
	  [(0 6)
 | 
			
		||||
	   nil "helpful description of the arguments to C functions" single])
 | 
			
		||||
 (mv-shell .
 | 
			
		||||
	   [(1 0)
 | 
			
		||||
	    nil "keep buffers in sync with filename throughout 'mv'commands in shell-mode." single])
 | 
			
		||||
 (diff-git .
 | 
			
		||||
	   [(0 1 1)
 | 
			
		||||
	    nil "Git integration with diff-mode" single])
 | 
			
		||||
 (html-script-src .
 | 
			
		||||
		  [(0 0 2)
 | 
			
		||||
		   nil "Insert <script src=\"..\"> for popular JavaScript libraries" single])
 | 
			
		||||
 (rvm .
 | 
			
		||||
      [(1 1)
 | 
			
		||||
       nil "Emacs integration for rvm" single])
 | 
			
		||||
 (elisp-depend .
 | 
			
		||||
	       [(0 4 1)
 | 
			
		||||
		nil "Parse depend libraries of elisp file." single])
 | 
			
		||||
 (perspective .
 | 
			
		||||
	      [(1 3)
 | 
			
		||||
	       nil "switch between named \"perspectives\" of the editor" single])
 | 
			
		||||
 (ruby-electric .
 | 
			
		||||
		[(1 1)
 | 
			
		||||
		 nil "electric editing commands for ruby files" single])
 | 
			
		||||
 (yari .
 | 
			
		||||
       [(0 3)
 | 
			
		||||
	nil "Yet Another RI interface for Emacs" single])
 | 
			
		||||
 (smex .
 | 
			
		||||
       [(1 1 1)
 | 
			
		||||
	nil "M-x interface with Ido-style fuzzy matching." single])
 | 
			
		||||
 (drag-stuff .
 | 
			
		||||
	     [(0 0 3)
 | 
			
		||||
	      nil "Drag stuff (lines, words, region, etc...) around" single])
 | 
			
		||||
 (ruby-test-mode .
 | 
			
		||||
		 [(1 0)
 | 
			
		||||
		  nil "Minor mode for Behaviour and Test Driven" single])
 | 
			
		||||
 (applescript-mode .
 | 
			
		||||
		   [(20090321)
 | 
			
		||||
		    nil "major mode for editing AppleScript source" single])
 | 
			
		||||
 (mediawiki .
 | 
			
		||||
	    [(1 1)
 | 
			
		||||
	     nil "mediawiki frontend" single])
 | 
			
		||||
 (wrap-region .
 | 
			
		||||
	      [(0 1 3)
 | 
			
		||||
	       nil "Wrap text with punctation or tag" single])
 | 
			
		||||
 (twitter .
 | 
			
		||||
	  [(20090422)
 | 
			
		||||
	   nil "Simple Emacs-based client for Twitter" single])
 | 
			
		||||
 (pastie .
 | 
			
		||||
	 [(20091230)
 | 
			
		||||
	  nil "Emacs integration for pastie.org" single])
 | 
			
		||||
 (textmate .
 | 
			
		||||
	   [(1)
 | 
			
		||||
	    nil "TextMate minor mode for Emacs" single])
 | 
			
		||||
 (yaml-mode .
 | 
			
		||||
	    [(0 0 5)
 | 
			
		||||
	     nil "Major mode for editing YAML files" single])
 | 
			
		||||
 (rspec-mode .
 | 
			
		||||
	     [(0 2)
 | 
			
		||||
	      ((ruby-mode
 | 
			
		||||
		(1 1)))
 | 
			
		||||
	      "Enhance ruby-mode for RSpec" single])
 | 
			
		||||
 (htmlize .
 | 
			
		||||
	  [(1 37)
 | 
			
		||||
	   nil "Convert buffer text and decorations to HTML." single])
 | 
			
		||||
 (swank-clojure .
 | 
			
		||||
		[(1 1 0)
 | 
			
		||||
		 ((slime-repl
 | 
			
		||||
		   (20091016))
 | 
			
		||||
		  (clojure-mode
 | 
			
		||||
		   (1 6)))
 | 
			
		||||
		 "slime adapter for clojure" single])
 | 
			
		||||
 (slime-repl .
 | 
			
		||||
	     [(20100404)
 | 
			
		||||
	      ((slime
 | 
			
		||||
		(20100404)))
 | 
			
		||||
	      "Read-Eval-Print Loop written in Emacs Lisp" single])
 | 
			
		||||
 (slime .
 | 
			
		||||
	[(20100404)
 | 
			
		||||
	 nil "Superior Lisp Interaction Mode for Emacs" single])
 | 
			
		||||
 (nterm .
 | 
			
		||||
	[(0 1)
 | 
			
		||||
	 nil "New TERMinal emulator" single])
 | 
			
		||||
 (sass-mode .
 | 
			
		||||
	    [(3 0 14)
 | 
			
		||||
	     ((haml-mode
 | 
			
		||||
	       (3 0 14)))
 | 
			
		||||
	     "Major mode for editing Sass files" single])
 | 
			
		||||
 (haml-mode .
 | 
			
		||||
	    [(3 0 14)
 | 
			
		||||
	     nil "Major mode for editing Haml files" single])
 | 
			
		||||
 (smart-tab .
 | 
			
		||||
	    [(0 3)
 | 
			
		||||
	     nil "Intelligent tab completion and indentation." single])
 | 
			
		||||
 (cssh .
 | 
			
		||||
       [(0 7)
 | 
			
		||||
	nil "clusterssh implementation for emacs" single])
 | 
			
		||||
 (relax .
 | 
			
		||||
	[(0 2)
 | 
			
		||||
	 ((json
 | 
			
		||||
	   (1 2))
 | 
			
		||||
	  (javascript
 | 
			
		||||
	   (1 99 8)))
 | 
			
		||||
	 "For browsing and interacting with CouchDB" single])
 | 
			
		||||
 (shellfm .
 | 
			
		||||
	  [(0 1)
 | 
			
		||||
	   nil "Emacs Shell.FM interface" single])
 | 
			
		||||
 (texdrive .
 | 
			
		||||
	   [(0 3 1)
 | 
			
		||||
	    nil "minor mode for creating png images from TeX formulae " single])
 | 
			
		||||
 (paredit .
 | 
			
		||||
	  [(20)
 | 
			
		||||
	   nil "Parenthesis-Editing Minor Mode" single])
 | 
			
		||||
 (rotate-text .
 | 
			
		||||
	      [(0 1)
 | 
			
		||||
	       nil "cycle through words, symbols and patterns" single])
 | 
			
		||||
 (full-ack .
 | 
			
		||||
	   [(0 2 1)
 | 
			
		||||
	    nil "a front-end for ack" single])
 | 
			
		||||
 (recent-addresses .
 | 
			
		||||
		   [(0 1)
 | 
			
		||||
		    nil "store and recall recently used email addresses" single])
 | 
			
		||||
 (test-case-mode .
 | 
			
		||||
		 [(0 1)
 | 
			
		||||
		  ((fringe-helper
 | 
			
		||||
		    (0 1 1)))
 | 
			
		||||
		  "unit test front-end" single])
 | 
			
		||||
 (nav .
 | 
			
		||||
      [(35)
 | 
			
		||||
       nil "Emacs mode for IDE-like navigation of directories" single])
 | 
			
		||||
 (company .
 | 
			
		||||
	  [(0 5)
 | 
			
		||||
	   nil "extensible inline text completion mechanism" tar])
 | 
			
		||||
 (guess-style .
 | 
			
		||||
	      [(0 1)
 | 
			
		||||
	       nil "automatic setting of code style variables" single])
 | 
			
		||||
 (clojure-test-mode .
 | 
			
		||||
		    [(1 4)
 | 
			
		||||
		     ((slime
 | 
			
		||||
		       (20091016))
 | 
			
		||||
		      (clojure-mode
 | 
			
		||||
		       (1 7)))
 | 
			
		||||
		     "Minor mode for Clojure tests" single])
 | 
			
		||||
 (clojure-mode .
 | 
			
		||||
	       [(1 7 1)
 | 
			
		||||
		nil "Major mode for Clojure code" single])
 | 
			
		||||
 (magit .
 | 
			
		||||
	[(0 8 1)
 | 
			
		||||
	 nil "control Git from Emacs." single])
 | 
			
		||||
 (w3 .
 | 
			
		||||
     [(4 0 46)
 | 
			
		||||
      nil "A web browser written entirely in Emacs Lisp" tar])
 | 
			
		||||
 (yasnippet-bundle .
 | 
			
		||||
		   [(0 6 1)
 | 
			
		||||
		    nil "Yet another snippet extension (Auto compiled bundle)" single])
 | 
			
		||||
 (rinari .
 | 
			
		||||
	 [(2 1)
 | 
			
		||||
	  ((ruby-mode
 | 
			
		||||
	    (1 1))
 | 
			
		||||
	   (inf-ruby
 | 
			
		||||
	    (2 1))
 | 
			
		||||
	   (ruby-compilation
 | 
			
		||||
	    (0 7))
 | 
			
		||||
	   (jump
 | 
			
		||||
	    (2 0)))
 | 
			
		||||
	  "Rinari Is Not A Rails IDE" single])
 | 
			
		||||
 (jump .
 | 
			
		||||
       [(2 0)
 | 
			
		||||
	((findr
 | 
			
		||||
	  (0 7))
 | 
			
		||||
	 (inflections
 | 
			
		||||
	  (1 0)))
 | 
			
		||||
	"build functions which contextually jump between files" single])
 | 
			
		||||
 (inflections .
 | 
			
		||||
	      [(1 0)
 | 
			
		||||
	       nil "convert english words between singular and plural" single])
 | 
			
		||||
 (tumble .
 | 
			
		||||
	 [(1 1)
 | 
			
		||||
	  ((http-post-simple
 | 
			
		||||
	    (1 0)))
 | 
			
		||||
	  "an Emacs mode for Tumblr" single])
 | 
			
		||||
 (http-post-simple .
 | 
			
		||||
		   [(1 0)
 | 
			
		||||
		    nil "HTTP POST requests using the url library" single])
 | 
			
		||||
 (findr .
 | 
			
		||||
	[(0 7)
 | 
			
		||||
	 nil "Breadth-first file-finding facility for (X)Emacs" single])
 | 
			
		||||
 (ruby-compilation .
 | 
			
		||||
		   [(0 7)
 | 
			
		||||
		    ((ruby-mode
 | 
			
		||||
		      (1 1))
 | 
			
		||||
		     (inf-ruby
 | 
			
		||||
		      (2 1)))
 | 
			
		||||
		    "run a ruby process in a compilation buffer" single])
 | 
			
		||||
 (gist .
 | 
			
		||||
       [(0 5)
 | 
			
		||||
	nil "Emacs integration for gist.github.com" single])
 | 
			
		||||
 (confluence .
 | 
			
		||||
	     [(1 4)
 | 
			
		||||
	      ((xml-rpc
 | 
			
		||||
		(1 6 4)))
 | 
			
		||||
	      "Emacs mode for interacting with confluence wikis" single])
 | 
			
		||||
 (epresent .
 | 
			
		||||
	   [(0 1)
 | 
			
		||||
	    nil "Simple presentation mode for Emacs" single])
 | 
			
		||||
 (inf-ruby .
 | 
			
		||||
	   [(2 1)
 | 
			
		||||
	    ((ruby-mode
 | 
			
		||||
	      (1 1)))
 | 
			
		||||
	    "Run a ruby process in a buffer" single])
 | 
			
		||||
 (ruby-mode .
 | 
			
		||||
	    [(1 1)
 | 
			
		||||
	     nil "Major mode for editing Ruby files" single])
 | 
			
		||||
 (idle-highlight .
 | 
			
		||||
		 [(1 0)
 | 
			
		||||
		  nil "highlight the word the point is on" single])
 | 
			
		||||
 (find-file-in-project .
 | 
			
		||||
		       [(2 0)
 | 
			
		||||
			((project-local-variables
 | 
			
		||||
			  (0 2)))
 | 
			
		||||
			"Find files in a project quickly." single])
 | 
			
		||||
 (project-local-variables .
 | 
			
		||||
			  [(0 2)
 | 
			
		||||
			   nil "set project-local variables from a file" single])
 | 
			
		||||
 (lusty-explorer .
 | 
			
		||||
		 [(2 4)
 | 
			
		||||
		  nil "Dynamic filesystem explorer and buffer switcher" single])
 | 
			
		||||
 (tempo-snippets .
 | 
			
		||||
		 [(0 1 5)
 | 
			
		||||
		  nil "visual insertion of tempo templates" single])
 | 
			
		||||
 (highlight-80+ .
 | 
			
		||||
		[(1 0)
 | 
			
		||||
		 nil "highlight characters beyond column 80" single])
 | 
			
		||||
 (echo-pick .
 | 
			
		||||
	    [(0 1)
 | 
			
		||||
	     nil "filter for echo area status messages" single])
 | 
			
		||||
 (fringe-helper .
 | 
			
		||||
		[(0 1 1)
 | 
			
		||||
		 nil "helper functions for fringe bitmaps" single])
 | 
			
		||||
 (elk-test .
 | 
			
		||||
	   [(0 3 2)
 | 
			
		||||
	    ((fringe-helper
 | 
			
		||||
	      (0 1 1)))
 | 
			
		||||
	    "Emacs Lisp testing framework" single])
 | 
			
		||||
 (compile-bookmarks .
 | 
			
		||||
		    [(0 2)
 | 
			
		||||
		     nil "bookmarks for compilation commands" single])
 | 
			
		||||
 (pov-mode .
 | 
			
		||||
	   [(3 2)
 | 
			
		||||
	    nil "Major mode for editing POV-Ray scene files." tar])
 | 
			
		||||
 (js2-mode .
 | 
			
		||||
	   [(20090723)
 | 
			
		||||
	    nil "an improved JavaScript editing mode" single])
 | 
			
		||||
 (ert .
 | 
			
		||||
      [(0 1)
 | 
			
		||||
       nil "Emacs Lisp Regression Testing" single])
 | 
			
		||||
 (jtags .
 | 
			
		||||
	[(0 96)
 | 
			
		||||
	 nil "enhanced tags functionality for Java development" single])
 | 
			
		||||
 (eproject .
 | 
			
		||||
	   [(0 4)
 | 
			
		||||
	    nil "project workspaces for emacs" tar])
 | 
			
		||||
 (log4j-mode .
 | 
			
		||||
	     [(1 3)
 | 
			
		||||
	      nil "major mode for viewing log files" single])
 | 
			
		||||
 (nxml-mode .
 | 
			
		||||
	    [(20041004)
 | 
			
		||||
	     nil "Major mode for editing XML documents." tar])
 | 
			
		||||
 (columnify .
 | 
			
		||||
	    [(1 0)
 | 
			
		||||
	     nil "arrange lines into columns" single])
 | 
			
		||||
 (gdb-mi .
 | 
			
		||||
	 [(0 6 1 0)
 | 
			
		||||
	  nil "User Interface for running GDB" single])
 | 
			
		||||
 (asciidoc .
 | 
			
		||||
	   [(0 1)
 | 
			
		||||
	    nil "asciidoc text file development support" single])
 | 
			
		||||
 (shell-current-directory .
 | 
			
		||||
			  [(0 1)
 | 
			
		||||
			   nil "create new shell based on buffer directory" single])
 | 
			
		||||
 (facebook .
 | 
			
		||||
	   [(0 0 1)
 | 
			
		||||
	    ((json
 | 
			
		||||
	      (0)))
 | 
			
		||||
	    "Access the Facebook API from emacs" single])
 | 
			
		||||
 (json .
 | 
			
		||||
       [(1 2)
 | 
			
		||||
	nil "JavaScript Object Notation parser / generator" single])
 | 
			
		||||
 (pick-backup .
 | 
			
		||||
	      [(0 8)
 | 
			
		||||
	       nil "easy access to versioned backup files" single])
 | 
			
		||||
 (idle-require .
 | 
			
		||||
	       [(1 0)
 | 
			
		||||
		nil "load elisp libraries while Emacs is idle" single])
 | 
			
		||||
 (highlight-symbol .
 | 
			
		||||
		   [(1 1)
 | 
			
		||||
		    nil "automatic and manual symbol highlighting" single])
 | 
			
		||||
 (auto-dictionary .
 | 
			
		||||
		  [(1 0 1)
 | 
			
		||||
		   nil "automatic dictionary switcher for flyspell" single])
 | 
			
		||||
 (dictionary .
 | 
			
		||||
	     [(1 8 7)
 | 
			
		||||
	      nil "an interface to an RFC 2229 dictionary server" tar])
 | 
			
		||||
 (muse .
 | 
			
		||||
       [(3 20)
 | 
			
		||||
	nil "Authoring and publishing tool" tar])
 | 
			
		||||
 (jimb-patch .
 | 
			
		||||
	     [(1 5)
 | 
			
		||||
	      nil "clean a patch for submission via email" single])
 | 
			
		||||
 (lisppaste .
 | 
			
		||||
	    [(1 8)
 | 
			
		||||
	     ((xml-rpc
 | 
			
		||||
	       (1 6 7)))
 | 
			
		||||
	     "Interact with the lisppaste pastebot via XML-RPC." single])
 | 
			
		||||
 (weblogger .
 | 
			
		||||
	    [(1 4 3)
 | 
			
		||||
	     ((xml-rpc
 | 
			
		||||
	       (1 6 5)))
 | 
			
		||||
	     "Weblog maintenance via XML-RPC APIs" single])
 | 
			
		||||
 (xml-rpc .
 | 
			
		||||
	  [(1 6 7)
 | 
			
		||||
	   nil "An elisp implementation of clientside XML-RPC" single])
 | 
			
		||||
 (iresize .
 | 
			
		||||
	  [(0 2)
 | 
			
		||||
	   nil "Interactively resize a window" single])
 | 
			
		||||
 (sgftree .
 | 
			
		||||
	  [(0 1)
 | 
			
		||||
	   nil "Read an sgf file and represent it as a tree" single])
 | 
			
		||||
 (chess .
 | 
			
		||||
	[(1 96)
 | 
			
		||||
	 nil "Play chess in Emacs" tar])
 | 
			
		||||
 (etags-select .
 | 
			
		||||
	       [(1 11)
 | 
			
		||||
		nil "Select from multiple tags" single])
 | 
			
		||||
 (less .
 | 
			
		||||
       [(0 2)
 | 
			
		||||
	nil "less style view mode" single])
 | 
			
		||||
 (smart-operator .
 | 
			
		||||
		 [(0 9)
 | 
			
		||||
		  nil "Insert operators packed with whitespaces smartly" single])
 | 
			
		||||
 (dired-isearch .
 | 
			
		||||
		[(0 3)
 | 
			
		||||
		 nil "isearch in Dired" single])
 | 
			
		||||
 (cal-china-x .
 | 
			
		||||
	      [(0 6)
 | 
			
		||||
	       nil "Chinese calendar extras" single])
 | 
			
		||||
 (wajig .
 | 
			
		||||
	[(0 53)
 | 
			
		||||
	 nil "an interface for wajig" single])
 | 
			
		||||
 (erc .
 | 
			
		||||
      [(5 3)
 | 
			
		||||
       nil "An Emacs Internet Relay Chat client" tar])
 | 
			
		||||
 (emms .
 | 
			
		||||
       [(3 0)
 | 
			
		||||
	nil "The Emacs Multimedia System" tar])
 | 
			
		||||
 (archive-downloader .
 | 
			
		||||
		     [(1 1)
 | 
			
		||||
		      nil "Download files from archive.org" single])
 | 
			
		||||
 (package .
 | 
			
		||||
	  [(0 9)
 | 
			
		||||
	   nil "Simple package system for Emacs" single])
 | 
			
		||||
 (highlight-parentheses .
 | 
			
		||||
			[(1 0 1)
 | 
			
		||||
			 nil "highlight surrounding parentheses" single])
 | 
			
		||||
 (kill-ring-search .
 | 
			
		||||
		   [(1 1)
 | 
			
		||||
		    nil "incremental search for the kill ring" single])
 | 
			
		||||
 (tex-math-preview .
 | 
			
		||||
		   [(8)
 | 
			
		||||
		    nil "preview TeX math expressions." single])
 | 
			
		||||
 (gtk-look .
 | 
			
		||||
	   [(19)
 | 
			
		||||
	    nil "lookup Gtk and Gnome documentation." single])
 | 
			
		||||
 (xtide .
 | 
			
		||||
	[(16)
 | 
			
		||||
	 nil "XTide display in Emacs" single])
 | 
			
		||||
 (compilation-recenter-end .
 | 
			
		||||
			   [(4)
 | 
			
		||||
			    nil "compilation-mode window recentre" single])
 | 
			
		||||
 (gdb-shell .
 | 
			
		||||
	    [(0 4)
 | 
			
		||||
	     nil "minor mode to add gdb features to shell" single])
 | 
			
		||||
 (highline .
 | 
			
		||||
	   [(4 2)
 | 
			
		||||
	    nil "minor mode to highlight current line in buffer" single])
 | 
			
		||||
 (lua-mode .
 | 
			
		||||
	   [(20100617)
 | 
			
		||||
	    nil "a major-mode for editing Lua scripts" single])
 | 
			
		||||
 (css-mode .
 | 
			
		||||
	   [(1 0)
 | 
			
		||||
	    nil "Major mode for editing Cascading Style Sheets" single])
 | 
			
		||||
 (javascript .
 | 
			
		||||
	     [(2 2 1)
 | 
			
		||||
	      nil "Major mode for editing JavaScript source text" single])
 | 
			
		||||
 (light-symbol .
 | 
			
		||||
	       [(0 1)
 | 
			
		||||
		nil "Minor mode to highlight symbol under point" single])
 | 
			
		||||
 (worklog .
 | 
			
		||||
	  [(2 4 2)
 | 
			
		||||
	   nil "time tracking mode" single])
 | 
			
		||||
 (abacus .
 | 
			
		||||
	 [(1 0 2)
 | 
			
		||||
	  nil "Abacus Calculator" single])
 | 
			
		||||
 (sudoku .
 | 
			
		||||
	 [(0 3)
 | 
			
		||||
	  nil "Simple sudoku game, can download puzzles from the web." single])
 | 
			
		||||
 (caps-mode .
 | 
			
		||||
	    [(1 0)
 | 
			
		||||
	     nil "(minor mode) letters are inserted capitalized" single])
 | 
			
		||||
 (lambdacalc .
 | 
			
		||||
	     [(1 0)
 | 
			
		||||
	      nil "Interpret lambda calculus expressions" single])
 | 
			
		||||
 (wtf .
 | 
			
		||||
      [(2 0)
 | 
			
		||||
       nil "Look up conversational and computing acronyms" single])
 | 
			
		||||
 (blank-mode .
 | 
			
		||||
	     [(6 6)
 | 
			
		||||
	      nil "Minor mode to visualize blanks" single])
 | 
			
		||||
 (bubbles .
 | 
			
		||||
	  [(0 5)
 | 
			
		||||
	   nil "Puzzle game for Emacs." single])
 | 
			
		||||
 (newsticker .
 | 
			
		||||
	     [(1 10)
 | 
			
		||||
	      nil "Headline news ticker" tar])
 | 
			
		||||
 (changelog-url .
 | 
			
		||||
		[(0 1)
 | 
			
		||||
		 nil "ChangeLog bugzilla buttonizer" tar]))
 | 
			
		||||
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
(1 (org              . [(20200824) ( ) "Outline-based notes management and organizer" tar])
 | 
			
		||||
   (org-plus-contrib . [(20200824) ( ) "Outline-based notes management and organizer" tar]))
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1 +0,0 @@
 | 
			
		||||
Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org> (trust undefined) created at 2020-08-29T11:05:02+0200 using RSA
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,174 +0,0 @@
 | 
			
		||||
;;; async-autoloads.el --- automatically extracted autoloads
 | 
			
		||||
;;
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(add-to-list 'load-path (directory-file-name
 | 
			
		||||
                         (or (file-name-directory #$) (car load-path))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "async" "async.el" (0 0 0 0))
 | 
			
		||||
;;; Generated autoloads from async.el
 | 
			
		||||
 | 
			
		||||
(autoload 'async-start-process "async" "\
 | 
			
		||||
Start the executable PROGRAM asynchronously named NAME.  See `async-start'.
 | 
			
		||||
PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the
 | 
			
		||||
process object when done.  If FINISH-FUNC is nil, the future
 | 
			
		||||
object will return the process object when the program is
 | 
			
		||||
finished.  Set DEFAULT-DIRECTORY to change PROGRAM's current
 | 
			
		||||
working directory.
 | 
			
		||||
 | 
			
		||||
\(fn NAME PROGRAM FINISH-FUNC &rest PROGRAM-ARGS)" nil nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'async-start "async" "\
 | 
			
		||||
Execute START-FUNC (often a lambda) in a subordinate Emacs process.
 | 
			
		||||
When done, the return value is passed to FINISH-FUNC.  Example:
 | 
			
		||||
 | 
			
		||||
    (async-start
 | 
			
		||||
       ;; What to do in the child process
 | 
			
		||||
       (lambda ()
 | 
			
		||||
         (message \"This is a test\")
 | 
			
		||||
         (sleep-for 3)
 | 
			
		||||
         222)
 | 
			
		||||
 | 
			
		||||
       ;; What to do when it finishes
 | 
			
		||||
       (lambda (result)
 | 
			
		||||
         (message \"Async process done, result should be 222: %s\"
 | 
			
		||||
                  result)))
 | 
			
		||||
 | 
			
		||||
If FINISH-FUNC is nil or missing, a future is returned that can
 | 
			
		||||
be inspected using `async-get', blocking until the value is
 | 
			
		||||
ready.  Example:
 | 
			
		||||
 | 
			
		||||
    (let ((proc (async-start
 | 
			
		||||
                   ;; What to do in the child process
 | 
			
		||||
                   (lambda ()
 | 
			
		||||
                     (message \"This is a test\")
 | 
			
		||||
                     (sleep-for 3)
 | 
			
		||||
                     222))))
 | 
			
		||||
 | 
			
		||||
        (message \"I'm going to do some work here\") ;; ....
 | 
			
		||||
 | 
			
		||||
        (message \"Waiting on async process, result should be 222: %s\"
 | 
			
		||||
                 (async-get proc)))
 | 
			
		||||
 | 
			
		||||
If you don't want to use a callback, and you don't care about any
 | 
			
		||||
return value from the child process, pass the `ignore' symbol as
 | 
			
		||||
the second argument (if you don't, and never call `async-get', it
 | 
			
		||||
will leave *emacs* process buffers hanging around):
 | 
			
		||||
 | 
			
		||||
    (async-start
 | 
			
		||||
     (lambda ()
 | 
			
		||||
       (delete-file \"a remote file on a slow link\" nil))
 | 
			
		||||
     'ignore)
 | 
			
		||||
 | 
			
		||||
Note: Even when FINISH-FUNC is present, a future is still
 | 
			
		||||
returned except that it yields no value (since the value is
 | 
			
		||||
passed to FINISH-FUNC).  Call `async-get' on such a future always
 | 
			
		||||
returns nil.  It can still be useful, however, as an argument to
 | 
			
		||||
`async-ready' or `async-wait'.
 | 
			
		||||
 | 
			
		||||
\(fn START-FUNC &optional FINISH-FUNC)" nil nil)
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "async" '("async-")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "async-bytecomp" "async-bytecomp.el" (0 0 0
 | 
			
		||||
;;;;;;  0))
 | 
			
		||||
;;; Generated autoloads from async-bytecomp.el
 | 
			
		||||
 | 
			
		||||
(autoload 'async-byte-recompile-directory "async-bytecomp" "\
 | 
			
		||||
Compile all *.el files in DIRECTORY asynchronously.
 | 
			
		||||
All *.elc files are systematically deleted before proceeding.
 | 
			
		||||
 | 
			
		||||
\(fn DIRECTORY &optional QUIET)" nil nil)
 | 
			
		||||
 | 
			
		||||
(defvar async-bytecomp-package-mode nil "\
 | 
			
		||||
Non-nil if Async-Bytecomp-Package mode is enabled.
 | 
			
		||||
See the `async-bytecomp-package-mode' command
 | 
			
		||||
for a description of this minor mode.
 | 
			
		||||
Setting this variable directly does not take effect;
 | 
			
		||||
either customize it (see the info node `Easy Customization')
 | 
			
		||||
or call the function `async-bytecomp-package-mode'.")
 | 
			
		||||
 | 
			
		||||
(custom-autoload 'async-bytecomp-package-mode "async-bytecomp" nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'async-bytecomp-package-mode "async-bytecomp" "\
 | 
			
		||||
Byte compile asynchronously packages installed with package.el.
 | 
			
		||||
Async compilation of packages can be controlled by
 | 
			
		||||
`async-bytecomp-allowed-packages'.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'async-byte-compile-file "async-bytecomp" "\
 | 
			
		||||
Byte compile Lisp code FILE asynchronously.
 | 
			
		||||
 | 
			
		||||
Same as `byte-compile-file' but asynchronous.
 | 
			
		||||
 | 
			
		||||
\(fn FILE)" t nil)
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "async-bytecomp" '("async-byte")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "dired-async" "dired-async.el" (0 0 0 0))
 | 
			
		||||
;;; Generated autoloads from dired-async.el
 | 
			
		||||
 | 
			
		||||
(defvar dired-async-mode nil "\
 | 
			
		||||
Non-nil if Dired-Async mode is enabled.
 | 
			
		||||
See the `dired-async-mode' command
 | 
			
		||||
for a description of this minor mode.
 | 
			
		||||
Setting this variable directly does not take effect;
 | 
			
		||||
either customize it (see the info node `Easy Customization')
 | 
			
		||||
or call the function `dired-async-mode'.")
 | 
			
		||||
 | 
			
		||||
(custom-autoload 'dired-async-mode "dired-async" nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'dired-async-mode "dired-async" "\
 | 
			
		||||
Do dired actions asynchronously.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'dired-async-do-copy "dired-async" "\
 | 
			
		||||
Run ‘dired-do-copy’ asynchronously.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'dired-async-do-symlink "dired-async" "\
 | 
			
		||||
Run ‘dired-do-symlink’ asynchronously.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'dired-async-do-hardlink "dired-async" "\
 | 
			
		||||
Run ‘dired-do-hardlink’ asynchronously.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'dired-async-do-rename "dired-async" "\
 | 
			
		||||
Run ‘dired-do-rename’ asynchronously.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dired-async" '("dired-async-")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "smtpmail-async" "smtpmail-async.el" (0 0 0
 | 
			
		||||
;;;;;;  0))
 | 
			
		||||
;;; Generated autoloads from smtpmail-async.el
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "smtpmail-async" '("async-smtpmail-")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil nil ("async-pkg.el") (0 0 0 0))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; version-control: never
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; no-update-autoloads: t
 | 
			
		||||
;; coding: utf-8
 | 
			
		||||
;; End:
 | 
			
		||||
;;; async-autoloads.el ends here
 | 
			
		||||
@@ -1,204 +0,0 @@
 | 
			
		||||
;;; async-bytecomp.el --- Compile elisp files asynchronously -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
;; Authors: John Wiegley <jwiegley@gmail.com>
 | 
			
		||||
;;          Thierry Volpiatto <thierry.volpiatto@gmail.com>
 | 
			
		||||
 | 
			
		||||
;; Keywords: dired async byte-compile
 | 
			
		||||
;; X-URL: https://github.com/jwiegley/dired-async
 | 
			
		||||
 | 
			
		||||
;; 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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
 | 
			
		||||
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
			
		||||
;; Boston, MA 02111-1307, USA.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
;;
 | 
			
		||||
;;  This package provide the `async-byte-recompile-directory' function
 | 
			
		||||
;;  which allows, as the name says to recompile a directory outside of
 | 
			
		||||
;;  your running emacs.
 | 
			
		||||
;;  The benefit is your files will be compiled in a clean environment without
 | 
			
		||||
;;  the old *.el files loaded.
 | 
			
		||||
;;  Among other things, this fix a bug in package.el which recompile
 | 
			
		||||
;;  the new files in the current environment with the old files loaded, creating
 | 
			
		||||
;;  errors in most packages after upgrades.
 | 
			
		||||
;;
 | 
			
		||||
;;  NB: This package is advicing the function `package--compile'.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(require 'async)
 | 
			
		||||
 | 
			
		||||
(defcustom async-bytecomp-allowed-packages 'all
 | 
			
		||||
  "Packages in this list will be compiled asynchronously by `package--compile'.
 | 
			
		||||
All the dependencies of these packages will be compiled async too,
 | 
			
		||||
so no need to add dependencies to this list.
 | 
			
		||||
The value of this variable can also be the symbol `all' (default), in this case
 | 
			
		||||
all packages are always compiled asynchronously."
 | 
			
		||||
  :group 'async
 | 
			
		||||
  :type '(choice
 | 
			
		||||
          (const :tag "All packages" all)
 | 
			
		||||
          (repeat symbol)))
 | 
			
		||||
 | 
			
		||||
(defvar async-byte-compile-log-file
 | 
			
		||||
  (concat user-emacs-directory "async-bytecomp.log"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun async-byte-recompile-directory (directory &optional quiet)
 | 
			
		||||
  "Compile all *.el files in DIRECTORY asynchronously.
 | 
			
		||||
All *.elc files are systematically deleted before proceeding."
 | 
			
		||||
  (cl-loop with dir = (directory-files directory t "\\.elc\\'")
 | 
			
		||||
           unless dir return nil
 | 
			
		||||
           for f in dir
 | 
			
		||||
           when (file-exists-p f) do (delete-file f))
 | 
			
		||||
  ;; Ensure async is reloaded when async.elc is deleted.
 | 
			
		||||
  ;; This happen when recompiling its own directory.
 | 
			
		||||
  (load "async")
 | 
			
		||||
  (let ((call-back
 | 
			
		||||
         (lambda (&optional _ignore)
 | 
			
		||||
           (if (file-exists-p async-byte-compile-log-file)
 | 
			
		||||
               (let ((buf (get-buffer-create byte-compile-log-buffer))
 | 
			
		||||
                     (n 0))
 | 
			
		||||
                 (with-current-buffer buf
 | 
			
		||||
                   (goto-char (point-max))
 | 
			
		||||
                   (let ((inhibit-read-only t))
 | 
			
		||||
                     (insert-file-contents async-byte-compile-log-file)
 | 
			
		||||
                     (compilation-mode))
 | 
			
		||||
                   (display-buffer buf)
 | 
			
		||||
                   (delete-file async-byte-compile-log-file)
 | 
			
		||||
                   (unless quiet
 | 
			
		||||
                     (save-excursion
 | 
			
		||||
                       (goto-char (point-min))
 | 
			
		||||
                       (while (re-search-forward "^.*:Error:" nil t)
 | 
			
		||||
                         (cl-incf n)))
 | 
			
		||||
                     (if (> n 0)
 | 
			
		||||
                         (message "Failed to compile %d files in directory `%s'" n directory)
 | 
			
		||||
                       (message "Directory `%s' compiled asynchronously with warnings" directory)))))
 | 
			
		||||
             (unless quiet
 | 
			
		||||
               (message "Directory `%s' compiled asynchronously with success" directory))))))
 | 
			
		||||
    (async-start
 | 
			
		||||
     `(lambda ()
 | 
			
		||||
        (require 'bytecomp)
 | 
			
		||||
        ,(async-inject-variables "\\`\\(load-path\\)\\|byte\\'")
 | 
			
		||||
        (let ((default-directory (file-name-as-directory ,directory))
 | 
			
		||||
              error-data)
 | 
			
		||||
          (add-to-list 'load-path default-directory)
 | 
			
		||||
          (byte-recompile-directory ,directory 0 t)
 | 
			
		||||
          (when (get-buffer byte-compile-log-buffer)
 | 
			
		||||
            (setq error-data (with-current-buffer byte-compile-log-buffer
 | 
			
		||||
                               (buffer-substring-no-properties (point-min) (point-max))))
 | 
			
		||||
            (unless (string= error-data "")
 | 
			
		||||
              (with-temp-file ,async-byte-compile-log-file
 | 
			
		||||
                (erase-buffer)
 | 
			
		||||
                (insert error-data))))))
 | 
			
		||||
     call-back)
 | 
			
		||||
    (unless quiet (message "Started compiling asynchronously directory %s" directory))))
 | 
			
		||||
 | 
			
		||||
(defvar package-archive-contents)
 | 
			
		||||
(defvar package-alist)
 | 
			
		||||
(declare-function package-desc-reqs "package.el" (cl-x))
 | 
			
		||||
 | 
			
		||||
(defun async-bytecomp--get-package-deps (pkgs)
 | 
			
		||||
  ;; Same as `package--get-deps' but parse instead `package-archive-contents'
 | 
			
		||||
  ;; because PKG is not already installed and not present in `package-alist'.
 | 
			
		||||
  ;; However fallback to `package-alist' in case PKG no more present
 | 
			
		||||
  ;; in `package-archive-contents' due to modification to `package-archives'.
 | 
			
		||||
  ;; See issue #58.
 | 
			
		||||
  (let ((seen '()))
 | 
			
		||||
    (while pkgs
 | 
			
		||||
      (let ((pkg (pop pkgs)))
 | 
			
		||||
        (unless (memq pkg seen)
 | 
			
		||||
          (let ((pkg-desc (cadr (or (assq pkg package-archive-contents)
 | 
			
		||||
                                    (assq pkg package-alist)))))
 | 
			
		||||
            (when pkg-desc
 | 
			
		||||
              (push pkg seen)
 | 
			
		||||
              (setq pkgs (append (mapcar #'car (package-desc-reqs pkg-desc))
 | 
			
		||||
                                 pkgs)))))))
 | 
			
		||||
    seen))
 | 
			
		||||
 | 
			
		||||
(defadvice package--compile (around byte-compile-async)
 | 
			
		||||
  (let ((cur-package (package-desc-name pkg-desc))
 | 
			
		||||
        (pkg-dir (package-desc-dir pkg-desc)))
 | 
			
		||||
    (if (or (member async-bytecomp-allowed-packages '(t all (all)))
 | 
			
		||||
            (memq cur-package (async-bytecomp--get-package-deps
 | 
			
		||||
                               async-bytecomp-allowed-packages)))
 | 
			
		||||
        (progn
 | 
			
		||||
          (when (eq cur-package 'async)
 | 
			
		||||
            (fmakunbound 'async-byte-recompile-directory))
 | 
			
		||||
          ;; Add to `load-path' the latest version of async and
 | 
			
		||||
          ;; reload it when reinstalling async.
 | 
			
		||||
          (when (string= cur-package "async")
 | 
			
		||||
            (cl-pushnew pkg-dir load-path)
 | 
			
		||||
            (load "async-bytecomp"))
 | 
			
		||||
          ;; `async-byte-recompile-directory' will add directory
 | 
			
		||||
          ;; as needed to `load-path'.
 | 
			
		||||
          (async-byte-recompile-directory (package-desc-dir pkg-desc) t))
 | 
			
		||||
      ad-do-it)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(define-minor-mode async-bytecomp-package-mode
 | 
			
		||||
  "Byte compile asynchronously packages installed with package.el.
 | 
			
		||||
Async compilation of packages can be controlled by
 | 
			
		||||
`async-bytecomp-allowed-packages'."
 | 
			
		||||
  :group 'async
 | 
			
		||||
  :global t
 | 
			
		||||
  (if async-bytecomp-package-mode
 | 
			
		||||
      (ad-activate 'package--compile)
 | 
			
		||||
    (ad-deactivate 'package--compile)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun async-byte-compile-file (file)
 | 
			
		||||
  "Byte compile Lisp code FILE asynchronously.
 | 
			
		||||
 | 
			
		||||
Same as `byte-compile-file' but asynchronous."
 | 
			
		||||
  (interactive "fFile: ")
 | 
			
		||||
  (let ((call-back
 | 
			
		||||
         (lambda (&optional _ignore)
 | 
			
		||||
           (let ((bn (file-name-nondirectory file)))
 | 
			
		||||
             (if (file-exists-p async-byte-compile-log-file)
 | 
			
		||||
                 (let ((buf (get-buffer-create byte-compile-log-buffer))
 | 
			
		||||
                       start)
 | 
			
		||||
                   (with-current-buffer buf
 | 
			
		||||
                     (goto-char (setq start (point-max)))
 | 
			
		||||
                     (let ((inhibit-read-only t))
 | 
			
		||||
                       (insert-file-contents async-byte-compile-log-file)
 | 
			
		||||
                       (compilation-mode))
 | 
			
		||||
                     (display-buffer buf)
 | 
			
		||||
                     (delete-file async-byte-compile-log-file)
 | 
			
		||||
                     (save-excursion
 | 
			
		||||
                       (goto-char start)
 | 
			
		||||
                       (if (re-search-forward "^.*:Error:" nil t)
 | 
			
		||||
                           (message "Failed to compile `%s'" bn)
 | 
			
		||||
                         (message "`%s' compiled asynchronously with warnings" bn)))))
 | 
			
		||||
               (message "`%s' compiled asynchronously with success" bn))))))
 | 
			
		||||
    (async-start
 | 
			
		||||
     `(lambda ()
 | 
			
		||||
        (require 'bytecomp)
 | 
			
		||||
        ,(async-inject-variables "\\`load-path\\'")
 | 
			
		||||
        (let ((default-directory ,(file-name-directory file)))
 | 
			
		||||
          (add-to-list 'load-path default-directory)
 | 
			
		||||
          (byte-compile-file ,file)
 | 
			
		||||
          (when (get-buffer byte-compile-log-buffer)
 | 
			
		||||
            (setq error-data (with-current-buffer byte-compile-log-buffer
 | 
			
		||||
                               (buffer-substring-no-properties (point-min) (point-max))))
 | 
			
		||||
            (unless (string= error-data "")
 | 
			
		||||
              (with-temp-file ,async-byte-compile-log-file
 | 
			
		||||
                (erase-buffer)
 | 
			
		||||
                (insert error-data))))))
 | 
			
		||||
     call-back)))
 | 
			
		||||
 | 
			
		||||
(provide 'async-bytecomp)
 | 
			
		||||
 | 
			
		||||
;;; async-bytecomp.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,8 +0,0 @@
 | 
			
		||||
(define-package "async" "20200809.501" "Asynchronous processing in Emacs"
 | 
			
		||||
  '((emacs "24.3"))
 | 
			
		||||
  :commit "36a10151e70e956e2f766ed9e65f4a9cfc8479b2" :keywords
 | 
			
		||||
  '("async")
 | 
			
		||||
  :url "https://github.com/jwiegley/emacs-async")
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; End:
 | 
			
		||||
@@ -1,408 +0,0 @@
 | 
			
		||||
;;; async.el --- Asynchronous processing  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
;; Author: John Wiegley <jwiegley@gmail.com>
 | 
			
		||||
;; Created: 18 Jun 2012
 | 
			
		||||
;; Version: 1.9.4
 | 
			
		||||
;; Package-Requires: ((emacs "24.3"))
 | 
			
		||||
;; Keywords: convenience async
 | 
			
		||||
;; URL: https://github.com/jwiegley/emacs-async
 | 
			
		||||
 | 
			
		||||
;; 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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
 | 
			
		||||
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
			
		||||
;; Boston, MA 02111-1307, USA.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Adds the ability to call asynchronous functions and process with ease.  See
 | 
			
		||||
;; the documentation for `async-start' and `async-start-process'.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile (require 'cl-lib))
 | 
			
		||||
 | 
			
		||||
(defgroup async nil
 | 
			
		||||
  "Simple asynchronous processing in Emacs"
 | 
			
		||||
  :group 'emacs)
 | 
			
		||||
 | 
			
		||||
(defcustom async-variables-noprops-function #'async--purecopy
 | 
			
		||||
  "Default function to remove text properties in variables."
 | 
			
		||||
  :group 'async
 | 
			
		||||
  :type 'function)
 | 
			
		||||
 | 
			
		||||
(defvar async-debug nil)
 | 
			
		||||
(defvar async-send-over-pipe t)
 | 
			
		||||
(defvar async-in-child-emacs nil)
 | 
			
		||||
(defvar async-callback nil)
 | 
			
		||||
(defvar async-callback-for-process nil)
 | 
			
		||||
(defvar async-callback-value nil)
 | 
			
		||||
(defvar async-callback-value-set nil)
 | 
			
		||||
(defvar async-current-process nil)
 | 
			
		||||
(defvar async--procvar nil)
 | 
			
		||||
 | 
			
		||||
(defun async--purecopy (object)
 | 
			
		||||
  "Remove text properties in OBJECT.
 | 
			
		||||
 | 
			
		||||
Argument OBJECT may be a list or a string, if anything else it
 | 
			
		||||
is returned unmodified."
 | 
			
		||||
  (cond ((stringp object)
 | 
			
		||||
         (substring-no-properties object))
 | 
			
		||||
        ((consp object)
 | 
			
		||||
         (cl-loop for elm in object
 | 
			
		||||
                  ;; A string.
 | 
			
		||||
                  if (stringp elm)
 | 
			
		||||
                  collect (substring-no-properties elm)
 | 
			
		||||
                  else
 | 
			
		||||
                  ;; Proper lists.
 | 
			
		||||
                  if (and (consp elm) (null (cdr (last elm))))
 | 
			
		||||
                  collect (async--purecopy elm)
 | 
			
		||||
                  else
 | 
			
		||||
                  ;; Dotted lists.
 | 
			
		||||
                  ;; We handle here only dotted list where car and cdr
 | 
			
		||||
                  ;; are atoms i.e. (x . y) and not (x . (x . y)) or
 | 
			
		||||
                  ;; (x . (x y)) which should fit most cases.
 | 
			
		||||
                  if (and (consp elm) (cdr (last elm)))
 | 
			
		||||
                  collect (let ((key (car elm))
 | 
			
		||||
                                (val (cdr elm)))
 | 
			
		||||
                            (cons (if (stringp key)
 | 
			
		||||
                                      (substring-no-properties key)
 | 
			
		||||
                                    key)
 | 
			
		||||
                                  (if (stringp val)
 | 
			
		||||
                                      (substring-no-properties val)
 | 
			
		||||
                                    val)))
 | 
			
		||||
                  else
 | 
			
		||||
                  collect elm))
 | 
			
		||||
        (t object)))
 | 
			
		||||
 | 
			
		||||
(defun async-inject-variables
 | 
			
		||||
    (include-regexp &optional predicate exclude-regexp noprops)
 | 
			
		||||
  "Return a `setq' form that replicates part of the calling environment.
 | 
			
		||||
 | 
			
		||||
It sets the value for every variable matching INCLUDE-REGEXP and
 | 
			
		||||
also PREDICATE.  It will not perform injection for any variable
 | 
			
		||||
matching EXCLUDE-REGEXP (if present) or representing a `syntax-table'
 | 
			
		||||
i.e. ending by \"-syntax-table\".
 | 
			
		||||
When NOPROPS is non nil it tries to strip out text properties of each
 | 
			
		||||
variable's value with `async-variables-noprops-function'.
 | 
			
		||||
 | 
			
		||||
It is intended to be used as follows:
 | 
			
		||||
 | 
			
		||||
    (async-start
 | 
			
		||||
       `(lambda ()
 | 
			
		||||
          (require 'smtpmail)
 | 
			
		||||
          (with-temp-buffer
 | 
			
		||||
            (insert ,(buffer-substring-no-properties (point-min) (point-max)))
 | 
			
		||||
            ;; Pass in the variable environment for smtpmail
 | 
			
		||||
            ,(async-inject-variables \"\\`\\(smtpmail\\|\\(user-\\)?mail\\)-\")
 | 
			
		||||
            (smtpmail-send-it)))
 | 
			
		||||
       'ignore)"
 | 
			
		||||
  `(setq
 | 
			
		||||
    ,@(let (bindings)
 | 
			
		||||
        (mapatoms
 | 
			
		||||
         (lambda (sym)
 | 
			
		||||
           (let* ((sname (and (boundp sym) (symbol-name sym)))
 | 
			
		||||
                  (value (and sname (symbol-value sym))))
 | 
			
		||||
             (when (and sname
 | 
			
		||||
                        (or (null include-regexp)
 | 
			
		||||
                            (string-match include-regexp sname))
 | 
			
		||||
                        (or (null exclude-regexp)
 | 
			
		||||
                            (not (string-match exclude-regexp sname)))
 | 
			
		||||
                        (not (string-match "-syntax-table\\'" sname)))
 | 
			
		||||
               (unless (or (stringp value)
 | 
			
		||||
                           (memq value '(nil t))
 | 
			
		||||
                           (numberp value)
 | 
			
		||||
                           (vectorp value))
 | 
			
		||||
                 (setq value `(quote ,value)))
 | 
			
		||||
               (when noprops
 | 
			
		||||
                 (setq value (funcall async-variables-noprops-function
 | 
			
		||||
                                      value)))
 | 
			
		||||
               (when (or (null predicate)
 | 
			
		||||
                         (funcall predicate sym))
 | 
			
		||||
                 (setq bindings (cons value bindings)
 | 
			
		||||
                       bindings (cons sym bindings)))))))
 | 
			
		||||
        bindings)))
 | 
			
		||||
 | 
			
		||||
(defalias 'async-inject-environment 'async-inject-variables)
 | 
			
		||||
 | 
			
		||||
(defun async-handle-result (func result buf)
 | 
			
		||||
  (if (null func)
 | 
			
		||||
      (progn
 | 
			
		||||
        (set (make-local-variable 'async-callback-value) result)
 | 
			
		||||
        (set (make-local-variable 'async-callback-value-set) t))
 | 
			
		||||
    (unwind-protect
 | 
			
		||||
        (if (and (listp result)
 | 
			
		||||
                 (eq 'async-signal (nth 0 result)))
 | 
			
		||||
            (signal (car (nth 1 result))
 | 
			
		||||
                    (cdr (nth 1 result)))
 | 
			
		||||
          (funcall func result))
 | 
			
		||||
      (unless async-debug
 | 
			
		||||
        (kill-buffer buf)))))
 | 
			
		||||
 | 
			
		||||
(defun async-when-done (proc &optional _change)
 | 
			
		||||
  "Process sentinel used to retrieve the value from the child process."
 | 
			
		||||
  (when (eq 'exit (process-status proc))
 | 
			
		||||
    (with-current-buffer (process-buffer proc)
 | 
			
		||||
      (let ((async-current-process proc))
 | 
			
		||||
        (if (= 0 (process-exit-status proc))
 | 
			
		||||
            (if async-callback-for-process
 | 
			
		||||
                (if async-callback
 | 
			
		||||
                    (prog1
 | 
			
		||||
                        (funcall async-callback proc)
 | 
			
		||||
                      (unless async-debug
 | 
			
		||||
                        (kill-buffer (current-buffer))))
 | 
			
		||||
                  (set (make-local-variable 'async-callback-value) proc)
 | 
			
		||||
                  (set (make-local-variable 'async-callback-value-set) t))
 | 
			
		||||
              (goto-char (point-max))
 | 
			
		||||
              (backward-sexp)
 | 
			
		||||
              (async-handle-result async-callback (read (current-buffer))
 | 
			
		||||
                                   (current-buffer)))
 | 
			
		||||
          (set (make-local-variable 'async-callback-value)
 | 
			
		||||
               (list 'error
 | 
			
		||||
                     (format "Async process '%s' failed with exit code %d"
 | 
			
		||||
                             (process-name proc) (process-exit-status proc))))
 | 
			
		||||
          (set (make-local-variable 'async-callback-value-set) t))))))
 | 
			
		||||
 | 
			
		||||
(defun async--receive-sexp (&optional stream)
 | 
			
		||||
  (let ((sexp (decode-coding-string (base64-decode-string
 | 
			
		||||
                                     (read stream)) 'utf-8-auto))
 | 
			
		||||
        ;; Parent expects UTF-8 encoded text.
 | 
			
		||||
        (coding-system-for-write 'utf-8-auto))
 | 
			
		||||
    (if async-debug
 | 
			
		||||
        (message "Received sexp {{{%s}}}" (pp-to-string sexp)))
 | 
			
		||||
    (setq sexp (read sexp))
 | 
			
		||||
    (if async-debug
 | 
			
		||||
        (message "Read sexp {{{%s}}}" (pp-to-string sexp)))
 | 
			
		||||
    (eval sexp)))
 | 
			
		||||
 | 
			
		||||
(defun async--insert-sexp (sexp)
 | 
			
		||||
  (let (print-level
 | 
			
		||||
        print-length
 | 
			
		||||
        (print-escape-nonascii t)
 | 
			
		||||
        (print-circle t))
 | 
			
		||||
    (prin1 sexp (current-buffer))
 | 
			
		||||
    ;; Just in case the string we're sending might contain EOF
 | 
			
		||||
    (encode-coding-region (point-min) (point-max) 'utf-8-auto)
 | 
			
		||||
    (base64-encode-region (point-min) (point-max) t)
 | 
			
		||||
    (goto-char (point-min)) (insert ?\")
 | 
			
		||||
    (goto-char (point-max)) (insert ?\" ?\n)))
 | 
			
		||||
 | 
			
		||||
(defun async--transmit-sexp (process sexp)
 | 
			
		||||
  (with-temp-buffer
 | 
			
		||||
    (if async-debug
 | 
			
		||||
        (message "Transmitting sexp {{{%s}}}" (pp-to-string sexp)))
 | 
			
		||||
    (async--insert-sexp sexp)
 | 
			
		||||
    (process-send-region process (point-min) (point-max))))
 | 
			
		||||
 | 
			
		||||
(defun async-batch-invoke ()
 | 
			
		||||
  "Called from the child Emacs process' command line."
 | 
			
		||||
  ;; Make sure 'message' and 'prin1' encode stuff in UTF-8, as parent
 | 
			
		||||
  ;; process expects.
 | 
			
		||||
  (let ((coding-system-for-write 'utf-8-auto))
 | 
			
		||||
    (setq async-in-child-emacs t
 | 
			
		||||
          debug-on-error async-debug)
 | 
			
		||||
    (if debug-on-error
 | 
			
		||||
        (prin1 (funcall
 | 
			
		||||
                (async--receive-sexp (unless async-send-over-pipe
 | 
			
		||||
                                       command-line-args-left))))
 | 
			
		||||
      (condition-case err
 | 
			
		||||
          (prin1 (funcall
 | 
			
		||||
                  (async--receive-sexp (unless async-send-over-pipe
 | 
			
		||||
                                         command-line-args-left))))
 | 
			
		||||
        (error
 | 
			
		||||
         (prin1 (list 'async-signal err)))))))
 | 
			
		||||
 | 
			
		||||
(defun async-ready (future)
 | 
			
		||||
  "Query a FUTURE to see if it is ready.
 | 
			
		||||
 | 
			
		||||
I.e., if no blocking
 | 
			
		||||
would result from a call to `async-get' on that FUTURE."
 | 
			
		||||
  (and (memq (process-status future) '(exit signal))
 | 
			
		||||
       (let ((buf (process-buffer future)))
 | 
			
		||||
         (if (buffer-live-p buf)
 | 
			
		||||
             (with-current-buffer buf
 | 
			
		||||
               async-callback-value-set)
 | 
			
		||||
           t))))
 | 
			
		||||
 | 
			
		||||
(defun async-wait (future)
 | 
			
		||||
  "Wait for FUTURE to become ready."
 | 
			
		||||
  (while (not (async-ready future))
 | 
			
		||||
    (sleep-for 0.05)))
 | 
			
		||||
 | 
			
		||||
(defun async-get (future)
 | 
			
		||||
  "Get the value from process FUTURE when it is ready.
 | 
			
		||||
FUTURE is returned by `async-start' or `async-start-process' when
 | 
			
		||||
its FINISH-FUNC is nil."
 | 
			
		||||
  (and future (async-wait future))
 | 
			
		||||
  (let ((buf (process-buffer future)))
 | 
			
		||||
    (when (buffer-live-p buf)
 | 
			
		||||
      (with-current-buffer buf
 | 
			
		||||
        (async-handle-result
 | 
			
		||||
         #'identity async-callback-value (current-buffer))))))
 | 
			
		||||
 | 
			
		||||
(defun async-message-p (value)
 | 
			
		||||
  "Return non-nil of VALUE is an async.el message packet."
 | 
			
		||||
  (and (listp value)
 | 
			
		||||
       (plist-get value :async-message)))
 | 
			
		||||
 | 
			
		||||
(defun async-send (&rest args)
 | 
			
		||||
  "Send the given messages to the asychronous Emacs PROCESS."
 | 
			
		||||
  (let ((args (append args '(:async-message t))))
 | 
			
		||||
    (if async-in-child-emacs
 | 
			
		||||
        (if async-callback
 | 
			
		||||
            (funcall async-callback args))
 | 
			
		||||
      (async--transmit-sexp (car args) (list 'quote (cdr args))))))
 | 
			
		||||
 | 
			
		||||
(defun async-receive ()
 | 
			
		||||
  "Send the given messages to the asychronous Emacs PROCESS."
 | 
			
		||||
  (async--receive-sexp))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun async-start-process (name program finish-func &rest program-args)
 | 
			
		||||
  "Start the executable PROGRAM asynchronously named NAME.  See `async-start'.
 | 
			
		||||
PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the
 | 
			
		||||
process object when done.  If FINISH-FUNC is nil, the future
 | 
			
		||||
object will return the process object when the program is
 | 
			
		||||
finished.  Set DEFAULT-DIRECTORY to change PROGRAM's current
 | 
			
		||||
working directory."
 | 
			
		||||
  (let* ((buf (generate-new-buffer (concat "*" name "*")))
 | 
			
		||||
         (proc (let ((process-connection-type nil))
 | 
			
		||||
                 (apply #'start-process name buf program program-args))))
 | 
			
		||||
    (with-current-buffer buf
 | 
			
		||||
      (set (make-local-variable 'async-callback) finish-func)
 | 
			
		||||
      (set-process-sentinel proc #'async-when-done)
 | 
			
		||||
      (unless (string= name "emacs")
 | 
			
		||||
        (set (make-local-variable 'async-callback-for-process) t))
 | 
			
		||||
      proc)))
 | 
			
		||||
 | 
			
		||||
(defvar async-quiet-switch "-Q"
 | 
			
		||||
  "The Emacs parameter to use to call emacs without config.
 | 
			
		||||
Can be one of \"-Q\" or \"-q\".
 | 
			
		||||
Default is \"-Q\" but it is sometimes useful to use \"-q\" to have a
 | 
			
		||||
enhanced config or some more variables loaded.")
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun async-start (start-func &optional finish-func)
 | 
			
		||||
  "Execute START-FUNC (often a lambda) in a subordinate Emacs process.
 | 
			
		||||
When done, the return value is passed to FINISH-FUNC.  Example:
 | 
			
		||||
 | 
			
		||||
    (async-start
 | 
			
		||||
       ;; What to do in the child process
 | 
			
		||||
       (lambda ()
 | 
			
		||||
         (message \"This is a test\")
 | 
			
		||||
         (sleep-for 3)
 | 
			
		||||
         222)
 | 
			
		||||
 | 
			
		||||
       ;; What to do when it finishes
 | 
			
		||||
       (lambda (result)
 | 
			
		||||
         (message \"Async process done, result should be 222: %s\"
 | 
			
		||||
                  result)))
 | 
			
		||||
 | 
			
		||||
If FINISH-FUNC is nil or missing, a future is returned that can
 | 
			
		||||
be inspected using `async-get', blocking until the value is
 | 
			
		||||
ready.  Example:
 | 
			
		||||
 | 
			
		||||
    (let ((proc (async-start
 | 
			
		||||
                   ;; What to do in the child process
 | 
			
		||||
                   (lambda ()
 | 
			
		||||
                     (message \"This is a test\")
 | 
			
		||||
                     (sleep-for 3)
 | 
			
		||||
                     222))))
 | 
			
		||||
 | 
			
		||||
        (message \"I'm going to do some work here\") ;; ....
 | 
			
		||||
 | 
			
		||||
        (message \"Waiting on async process, result should be 222: %s\"
 | 
			
		||||
                 (async-get proc)))
 | 
			
		||||
 | 
			
		||||
If you don't want to use a callback, and you don't care about any
 | 
			
		||||
return value from the child process, pass the `ignore' symbol as
 | 
			
		||||
the second argument (if you don't, and never call `async-get', it
 | 
			
		||||
will leave *emacs* process buffers hanging around):
 | 
			
		||||
 | 
			
		||||
    (async-start
 | 
			
		||||
     (lambda ()
 | 
			
		||||
       (delete-file \"a remote file on a slow link\" nil))
 | 
			
		||||
     'ignore)
 | 
			
		||||
 | 
			
		||||
Note: Even when FINISH-FUNC is present, a future is still
 | 
			
		||||
returned except that it yields no value (since the value is
 | 
			
		||||
passed to FINISH-FUNC).  Call `async-get' on such a future always
 | 
			
		||||
returns nil.  It can still be useful, however, as an argument to
 | 
			
		||||
`async-ready' or `async-wait'."
 | 
			
		||||
  (let ((sexp start-func)
 | 
			
		||||
        ;; Subordinate Emacs will send text encoded in UTF-8.
 | 
			
		||||
        (coding-system-for-read 'utf-8-auto))
 | 
			
		||||
    (setq async--procvar
 | 
			
		||||
          (async-start-process
 | 
			
		||||
           "emacs" (file-truename
 | 
			
		||||
                    (expand-file-name invocation-name
 | 
			
		||||
                                      invocation-directory))
 | 
			
		||||
           finish-func
 | 
			
		||||
           async-quiet-switch "-l"
 | 
			
		||||
           ;; Using `locate-library' ensure we use the right file
 | 
			
		||||
           ;; when the .elc have been deleted.
 | 
			
		||||
           (locate-library "async")
 | 
			
		||||
           "-batch" "-f" "async-batch-invoke"
 | 
			
		||||
           (if async-send-over-pipe
 | 
			
		||||
               "<none>"
 | 
			
		||||
             (with-temp-buffer
 | 
			
		||||
               (async--insert-sexp (list 'quote sexp))
 | 
			
		||||
               (buffer-string)))))
 | 
			
		||||
    (if async-send-over-pipe
 | 
			
		||||
        (async--transmit-sexp async--procvar (list 'quote sexp)))
 | 
			
		||||
    async--procvar))
 | 
			
		||||
 | 
			
		||||
(defmacro async-sandbox(func)
 | 
			
		||||
  "Evaluate FUNC in a separate Emacs process, synchronously."
 | 
			
		||||
  `(async-get (async-start ,func)))
 | 
			
		||||
 | 
			
		||||
(defun async--fold-left (fn forms bindings)
 | 
			
		||||
  (let ((res forms))
 | 
			
		||||
    (dolist (binding bindings)
 | 
			
		||||
      (setq res (funcall fn res
 | 
			
		||||
                         (if (listp binding)
 | 
			
		||||
                             binding
 | 
			
		||||
                           (list binding)))))
 | 
			
		||||
    res))
 | 
			
		||||
 | 
			
		||||
(defmacro async-let (bindings &rest forms)
 | 
			
		||||
  "Implements `let', but each binding is established asynchronously.
 | 
			
		||||
For example:
 | 
			
		||||
 | 
			
		||||
  (async-let ((x (foo))
 | 
			
		||||
              (y (bar)))
 | 
			
		||||
     (message \"%s %s\" x y))
 | 
			
		||||
 | 
			
		||||
    expands to ==>
 | 
			
		||||
 | 
			
		||||
  (async-start (foo)
 | 
			
		||||
   (lambda (x)
 | 
			
		||||
     (async-start (bar)
 | 
			
		||||
      (lambda (y)
 | 
			
		||||
        (message \"%s %s\" x y)))))"
 | 
			
		||||
  (declare (indent 1))
 | 
			
		||||
  (async--fold-left
 | 
			
		||||
   (lambda (acc binding)
 | 
			
		||||
     (let ((fun (pcase (cadr binding)
 | 
			
		||||
                  ((and (pred functionp) f) f)
 | 
			
		||||
                  (f `(lambda () ,f)))))
 | 
			
		||||
       `(async-start ,fun
 | 
			
		||||
                     (lambda (,(car binding))
 | 
			
		||||
                       ,acc))))
 | 
			
		||||
   `(progn ,@forms)
 | 
			
		||||
   (reverse bindings)))
 | 
			
		||||
 | 
			
		||||
(provide 'async)
 | 
			
		||||
 | 
			
		||||
;;; async.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,408 +0,0 @@
 | 
			
		||||
;;; dired-async.el --- Asynchronous dired actions -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
;; Authors: John Wiegley <jwiegley@gmail.com>
 | 
			
		||||
;;          Thierry Volpiatto <thierry.volpiatto@gmail.com>
 | 
			
		||||
 | 
			
		||||
;; Keywords: dired async network
 | 
			
		||||
;; X-URL: https://github.com/jwiegley/dired-async
 | 
			
		||||
 | 
			
		||||
;; 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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
 | 
			
		||||
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
			
		||||
;; Boston, MA 02111-1307, USA.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This file provide a redefinition of `dired-create-file' function,
 | 
			
		||||
;; performs copies, moves and all what is handled by `dired-create-file'
 | 
			
		||||
;; in the background using a slave Emacs process,
 | 
			
		||||
;; by means of the async.el module.
 | 
			
		||||
;; To use it, put this in your .emacs:
 | 
			
		||||
 | 
			
		||||
;;     (dired-async-mode 1)
 | 
			
		||||
 | 
			
		||||
;; This will enable async copy/rename etc...
 | 
			
		||||
;; in dired and helm.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(require 'dired-aux)
 | 
			
		||||
(require 'async)
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (defvar async-callback))
 | 
			
		||||
 | 
			
		||||
(defgroup dired-async nil
 | 
			
		||||
  "Copy rename files asynchronously from dired."
 | 
			
		||||
  :group 'dired)
 | 
			
		||||
 | 
			
		||||
(defcustom dired-async-env-variables-regexp
 | 
			
		||||
  "\\`\\(tramp-\\(default\\|connection\\|remote\\)\\|ange-ftp\\)-.*"
 | 
			
		||||
  "Variables matching this regexp will be loaded on Child Emacs."
 | 
			
		||||
  :type  'regexp
 | 
			
		||||
  :group 'dired-async)
 | 
			
		||||
 | 
			
		||||
(defcustom dired-async-message-function 'dired-async-mode-line-message
 | 
			
		||||
  "Function to use to notify result when operation finish.
 | 
			
		||||
Should take same args as `message'."
 | 
			
		||||
  :group 'dired-async
 | 
			
		||||
  :type  'function)
 | 
			
		||||
 | 
			
		||||
(defcustom dired-async-log-file "/tmp/dired-async.log"
 | 
			
		||||
  "File use to communicate errors from Child Emacs to host Emacs."
 | 
			
		||||
  :group 'dired-async
 | 
			
		||||
  :type 'string)
 | 
			
		||||
 | 
			
		||||
(defcustom dired-async-mode-lighter '(:eval
 | 
			
		||||
                                      (when (eq major-mode 'dired-mode)
 | 
			
		||||
                                        " Async"))
 | 
			
		||||
  "Mode line lighter used for `dired-async-mode'."
 | 
			
		||||
  :group 'dired-async
 | 
			
		||||
  :risky t
 | 
			
		||||
  :type 'sexp)
 | 
			
		||||
 | 
			
		||||
(defface dired-async-message
 | 
			
		||||
  '((t (:foreground "yellow")))
 | 
			
		||||
  "Face used for mode-line message."
 | 
			
		||||
  :group 'dired-async)
 | 
			
		||||
 | 
			
		||||
(defface dired-async-failures
 | 
			
		||||
  '((t (:foreground "red")))
 | 
			
		||||
  "Face used for mode-line message."
 | 
			
		||||
  :group 'dired-async)
 | 
			
		||||
 | 
			
		||||
(defface dired-async-mode-message
 | 
			
		||||
  '((t (:foreground "Gold")))
 | 
			
		||||
  "Face used for `dired-async--modeline-mode' lighter."
 | 
			
		||||
  :group 'dired-async)
 | 
			
		||||
 | 
			
		||||
(define-minor-mode dired-async--modeline-mode
 | 
			
		||||
  "Notify mode-line that an async process run."
 | 
			
		||||
  :group 'dired-async
 | 
			
		||||
  :global t
 | 
			
		||||
  :lighter (:eval (propertize (format " [%s Async job(s) running]"
 | 
			
		||||
                                      (length (dired-async-processes)))
 | 
			
		||||
                              'face 'dired-async-mode-message))
 | 
			
		||||
  (unless dired-async--modeline-mode
 | 
			
		||||
    (let ((visible-bell t)) (ding))))
 | 
			
		||||
 | 
			
		||||
(defun dired-async-mode-line-message (text face &rest args)
 | 
			
		||||
  "Notify end of operation in `mode-line'."
 | 
			
		||||
  (message nil)
 | 
			
		||||
  (let ((mode-line-format (concat
 | 
			
		||||
                           " " (propertize
 | 
			
		||||
                                (if args
 | 
			
		||||
                                    (apply #'format text args)
 | 
			
		||||
                                  text)
 | 
			
		||||
                                'face face))))
 | 
			
		||||
    (force-mode-line-update)
 | 
			
		||||
    (sit-for 3)
 | 
			
		||||
    (force-mode-line-update)))
 | 
			
		||||
 | 
			
		||||
(defun dired-async-processes ()
 | 
			
		||||
  (cl-loop for p in (process-list)
 | 
			
		||||
           when (cl-loop for c in (process-command p) thereis
 | 
			
		||||
                         (string= "async-batch-invoke" c))
 | 
			
		||||
           collect p))
 | 
			
		||||
 | 
			
		||||
(defun dired-async-kill-process ()
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (let* ((processes (dired-async-processes))
 | 
			
		||||
         (proc (car (last processes))))
 | 
			
		||||
    (and proc (delete-process proc))
 | 
			
		||||
    (unless (> (length processes) 1)
 | 
			
		||||
      (dired-async--modeline-mode -1))))
 | 
			
		||||
 | 
			
		||||
(defun dired-async-after-file-create (total operation failures skipped)
 | 
			
		||||
  "Callback function used for operation handled by `dired-create-file'."
 | 
			
		||||
  (unless (dired-async-processes)
 | 
			
		||||
    ;; Turn off mode-line notification
 | 
			
		||||
    ;; only when last process end.
 | 
			
		||||
    (dired-async--modeline-mode -1))
 | 
			
		||||
  (when operation
 | 
			
		||||
    (if (file-exists-p dired-async-log-file)
 | 
			
		||||
        (progn
 | 
			
		||||
          (pop-to-buffer (get-buffer-create dired-log-buffer))
 | 
			
		||||
          (goto-char (point-max))
 | 
			
		||||
          (setq inhibit-read-only t)
 | 
			
		||||
          (insert "Error: ")
 | 
			
		||||
          (insert-file-contents dired-async-log-file)
 | 
			
		||||
          (special-mode)
 | 
			
		||||
          (shrink-window-if-larger-than-buffer)
 | 
			
		||||
          (delete-file dired-async-log-file))
 | 
			
		||||
      (run-with-timer
 | 
			
		||||
       0.1 nil
 | 
			
		||||
       (lambda ()
 | 
			
		||||
         ;; First send error messages.
 | 
			
		||||
         (cond (failures
 | 
			
		||||
                (funcall dired-async-message-function
 | 
			
		||||
                         "%s failed for %d of %d file%s -- See *Dired log* buffer"
 | 
			
		||||
                         'dired-async-failures
 | 
			
		||||
                         (car operation) (length failures)
 | 
			
		||||
                         total (dired-plural-s total)))
 | 
			
		||||
               (skipped
 | 
			
		||||
                (funcall dired-async-message-function
 | 
			
		||||
                         "%s: %d of %d file%s skipped -- See *Dired log* buffer"
 | 
			
		||||
                         'dired-async-failures
 | 
			
		||||
                         (car operation) (length skipped) total
 | 
			
		||||
                         (dired-plural-s total))))
 | 
			
		||||
         (when dired-buffers
 | 
			
		||||
           (cl-loop for (_f . b) in dired-buffers
 | 
			
		||||
                    when (buffer-live-p b)
 | 
			
		||||
                    do (with-current-buffer b
 | 
			
		||||
                         (when (and (not (file-remote-p default-directory nil t))
 | 
			
		||||
                                    (file-exists-p default-directory))
 | 
			
		||||
                           (revert-buffer nil t)))))
 | 
			
		||||
         ;; Finally send the success message.
 | 
			
		||||
         (funcall dired-async-message-function
 | 
			
		||||
                  "Asynchronous %s of %s on %s file%s done"
 | 
			
		||||
                  'dired-async-message
 | 
			
		||||
                  (car operation) (cadr operation)
 | 
			
		||||
                  total (dired-plural-s total)))))))
 | 
			
		||||
 | 
			
		||||
(defun dired-async-maybe-kill-ftp ()
 | 
			
		||||
  "Return a form to kill ftp process in child emacs."
 | 
			
		||||
  (quote
 | 
			
		||||
   (progn
 | 
			
		||||
     (require 'cl-lib)
 | 
			
		||||
     (let ((buf (cl-loop for b in (buffer-list)
 | 
			
		||||
                         thereis (and (string-match
 | 
			
		||||
                                       "\\`\\*ftp.*"
 | 
			
		||||
                                       (buffer-name b)) b))))
 | 
			
		||||
       (when buf (kill-buffer buf))))))
 | 
			
		||||
 | 
			
		||||
(defvar overwrite-query)
 | 
			
		||||
(defun dired-async-create-files (file-creator operation fn-list name-constructor
 | 
			
		||||
                                              &optional _marker-char)
 | 
			
		||||
  "Same as `dired-create-files' but asynchronous.
 | 
			
		||||
 | 
			
		||||
See `dired-create-files' for the behavior of arguments."
 | 
			
		||||
  (setq overwrite-query nil)
 | 
			
		||||
  (let ((total (length fn-list))
 | 
			
		||||
        failures async-fn-list skipped callback
 | 
			
		||||
        async-quiet-switch)
 | 
			
		||||
    (let (to)
 | 
			
		||||
      (dolist (from fn-list)
 | 
			
		||||
        (setq to (funcall name-constructor from))
 | 
			
		||||
        (if (and (equal to from)
 | 
			
		||||
                 (null (eq file-creator 'backup-file)))
 | 
			
		||||
            (progn
 | 
			
		||||
              (setq to nil)
 | 
			
		||||
              (dired-log "Cannot %s to same file: %s\n"
 | 
			
		||||
                         (downcase operation) from)))
 | 
			
		||||
        (if (not to)
 | 
			
		||||
            (setq skipped (cons (dired-make-relative from) skipped))
 | 
			
		||||
          (let* ((overwrite (and (null (eq file-creator 'backup-file))
 | 
			
		||||
                                 (file-exists-p to)))
 | 
			
		||||
                 (dired-overwrite-confirmed ; for dired-handle-overwrite
 | 
			
		||||
                  (and overwrite
 | 
			
		||||
                       (let ((help-form `(format "\
 | 
			
		||||
Type SPC or `y' to overwrite file `%s',
 | 
			
		||||
DEL or `n' to skip to next,
 | 
			
		||||
ESC or `q' to not overwrite any of the remaining files,
 | 
			
		||||
`!' to overwrite all remaining files with no more questions." ,to)))
 | 
			
		||||
                         (dired-query 'overwrite-query "Overwrite `%s'?" to)))))
 | 
			
		||||
            ;; Handle the `dired-copy-file' file-creator specially
 | 
			
		||||
            ;; When copying a directory to another directory or
 | 
			
		||||
            ;; possibly to itself or one of its subdirectories.
 | 
			
		||||
            ;; e.g "~/foo/" => "~/test/"
 | 
			
		||||
            ;; or "~/foo/" =>"~/foo/"
 | 
			
		||||
            ;; or "~/foo/ => ~/foo/bar/")
 | 
			
		||||
            ;; In this case the 'name-constructor' have set the destination
 | 
			
		||||
            ;; TO to "~/test/foo" because the old emacs23 behavior
 | 
			
		||||
            ;; of `copy-directory' was to not create the subdirectory
 | 
			
		||||
            ;; and instead copy the contents.
 | 
			
		||||
            ;; With the new behavior of `copy-directory'
 | 
			
		||||
            ;; (similar to the `cp' shell command) we don't
 | 
			
		||||
            ;; need such a construction of the target directory,
 | 
			
		||||
            ;; so modify the destination TO to "~/test/" instead of "~/test/foo/".
 | 
			
		||||
            (let ((destname (file-name-directory to)))
 | 
			
		||||
              (when (and (file-directory-p from)
 | 
			
		||||
                         (file-directory-p to)
 | 
			
		||||
                         (eq file-creator 'dired-copy-file))
 | 
			
		||||
                (setq to destname))
 | 
			
		||||
              ;; If DESTNAME is a subdirectory of FROM, not a symlink,
 | 
			
		||||
              ;; and the method in use is copying, signal an error.
 | 
			
		||||
              (and (eq t (car (file-attributes destname)))
 | 
			
		||||
                   (eq file-creator 'dired-copy-file)
 | 
			
		||||
                   (file-in-directory-p destname from)
 | 
			
		||||
                   (error "Cannot copy `%s' into its subdirectory `%s'"
 | 
			
		||||
                          from to)))
 | 
			
		||||
            (if overwrite
 | 
			
		||||
                (or (and dired-overwrite-confirmed
 | 
			
		||||
                         (push (cons from to) async-fn-list))
 | 
			
		||||
                    (progn
 | 
			
		||||
                      (push (dired-make-relative from) failures)
 | 
			
		||||
                      (dired-log "%s `%s' to `%s' failed\n"
 | 
			
		||||
                                 operation from to)))
 | 
			
		||||
              (push (cons from to) async-fn-list)))))
 | 
			
		||||
      ;; Fix tramp issue #80 with emacs-26, use "-q" only when needed.
 | 
			
		||||
      (setq async-quiet-switch
 | 
			
		||||
            (if (and (boundp 'tramp-cache-read-persistent-data)
 | 
			
		||||
                     async-fn-list
 | 
			
		||||
                     (cl-loop for (_from . to) in async-fn-list
 | 
			
		||||
                              thereis (file-remote-p to)))
 | 
			
		||||
                "-q" "-Q"))
 | 
			
		||||
      ;; When failures have been printed to dired log add the date at bob.
 | 
			
		||||
      (when (or failures skipped) (dired-log t))
 | 
			
		||||
      ;; When async-fn-list is empty that's mean only one file
 | 
			
		||||
      ;; had to be copied and user finally answer NO.
 | 
			
		||||
      ;; In this case async process will never start and callback
 | 
			
		||||
      ;; will have no chance to run, so notify failures here.
 | 
			
		||||
      (unless async-fn-list
 | 
			
		||||
        (cond (failures
 | 
			
		||||
               (funcall dired-async-message-function
 | 
			
		||||
                        "%s failed for %d of %d file%s -- See *Dired log* buffer"
 | 
			
		||||
                        'dired-async-failures
 | 
			
		||||
                        operation (length failures)
 | 
			
		||||
                        total (dired-plural-s total)))
 | 
			
		||||
              (skipped
 | 
			
		||||
               (funcall dired-async-message-function
 | 
			
		||||
                        "%s: %d of %d file%s skipped -- See *Dired log* buffer"
 | 
			
		||||
                        'dired-async-failures
 | 
			
		||||
                        operation (length skipped) total
 | 
			
		||||
                        (dired-plural-s total)))))
 | 
			
		||||
      ;; Setup callback.
 | 
			
		||||
      (setq callback
 | 
			
		||||
            (lambda (&optional _ignore)
 | 
			
		||||
              (dired-async-after-file-create
 | 
			
		||||
               total (list operation (length async-fn-list)) failures skipped)
 | 
			
		||||
              (when (string= (downcase operation) "rename")
 | 
			
		||||
                (cl-loop for (file . to) in async-fn-list
 | 
			
		||||
                         for bf = (get-file-buffer file)
 | 
			
		||||
                         for destp = (file-exists-p to)
 | 
			
		||||
                         do (and bf destp
 | 
			
		||||
                                 (with-current-buffer bf
 | 
			
		||||
                                   (set-visited-file-name to t t))))))))
 | 
			
		||||
    ;; Start async process.
 | 
			
		||||
    (when async-fn-list
 | 
			
		||||
      (async-start `(lambda ()
 | 
			
		||||
                      (require 'cl-lib) (require 'dired-aux) (require 'dired-x)
 | 
			
		||||
                      ,(async-inject-variables dired-async-env-variables-regexp)
 | 
			
		||||
                      (let ((dired-recursive-copies (quote always))
 | 
			
		||||
                            (dired-copy-preserve-time
 | 
			
		||||
                             ,dired-copy-preserve-time))
 | 
			
		||||
                        (setq overwrite-backup-query nil)
 | 
			
		||||
                        ;; Inline `backup-file' as long as it is not
 | 
			
		||||
                        ;; available in emacs.
 | 
			
		||||
                        (defalias 'backup-file
 | 
			
		||||
                          ;; Same feature as "cp -f --backup=numbered from to"
 | 
			
		||||
                          ;; Symlinks are copied as file from source unlike
 | 
			
		||||
                          ;; `dired-copy-file' which is same as cp -d.
 | 
			
		||||
                          ;; Directories are omitted.
 | 
			
		||||
                          (lambda (from to ok)
 | 
			
		||||
                            (cond ((file-directory-p from) (ignore))
 | 
			
		||||
                                  (t (let ((count 0))
 | 
			
		||||
                                       (while (let ((attrs (file-attributes to)))
 | 
			
		||||
                                                (and attrs (null (nth 0 attrs))))
 | 
			
		||||
                                         (cl-incf count)
 | 
			
		||||
                                         (setq to (concat (file-name-sans-versions to)
 | 
			
		||||
                                                          (format ".~%s~" count)))))
 | 
			
		||||
                                     (condition-case err
 | 
			
		||||
                                         (copy-file from to ok dired-copy-preserve-time)
 | 
			
		||||
                                       (file-date-error
 | 
			
		||||
                                        (dired-log "Can't set date on %s:\n%s\n" from err)))))))
 | 
			
		||||
                        ;; Now run the FILE-CREATOR function on files.
 | 
			
		||||
                        (cl-loop with fn = (quote ,file-creator)
 | 
			
		||||
                                 for (from . dest) in (quote ,async-fn-list)
 | 
			
		||||
                                 do (condition-case err
 | 
			
		||||
                                        (funcall fn from dest t)
 | 
			
		||||
                                      (file-error
 | 
			
		||||
                                       (dired-log "%s: %s\n" (car err) (cdr err)))
 | 
			
		||||
                                      nil))
 | 
			
		||||
                        (when (get-buffer dired-log-buffer)
 | 
			
		||||
                          (dired-log t)
 | 
			
		||||
                          (with-current-buffer dired-log-buffer
 | 
			
		||||
                            (write-region (point-min) (point-max)
 | 
			
		||||
                                          ,dired-async-log-file))))
 | 
			
		||||
                      ,(dired-async-maybe-kill-ftp))
 | 
			
		||||
                   callback)
 | 
			
		||||
      ;; Run mode-line notifications while process running.
 | 
			
		||||
      (dired-async--modeline-mode 1)
 | 
			
		||||
      (message "%s proceeding asynchronously..." operation))))
 | 
			
		||||
 | 
			
		||||
(defvar wdired-use-interactive-rename)
 | 
			
		||||
(defun dired-async-wdired-do-renames (old-fn &rest args)
 | 
			
		||||
  ;; Perhaps a better fix would be to ask for renaming BEFORE starting
 | 
			
		||||
  ;; OLD-FN when `wdired-use-interactive-rename' is non-nil.  For now
 | 
			
		||||
  ;; just bind it to nil to ensure no questions will be asked between
 | 
			
		||||
  ;; each rename.
 | 
			
		||||
  (let (wdired-use-interactive-rename)
 | 
			
		||||
    (apply old-fn args)))
 | 
			
		||||
 | 
			
		||||
(defadvice wdired-do-renames (around wdired-async)
 | 
			
		||||
  (let (wdired-use-interactive-rename)
 | 
			
		||||
    ad-do-it))
 | 
			
		||||
 | 
			
		||||
(defadvice dired-create-files (around dired-async)
 | 
			
		||||
  (dired-async-create-files file-creator operation fn-list
 | 
			
		||||
                            name-constructor marker-char))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(define-minor-mode dired-async-mode
 | 
			
		||||
  "Do dired actions asynchronously."
 | 
			
		||||
  :group 'dired-async
 | 
			
		||||
  :lighter dired-async-mode-lighter
 | 
			
		||||
  :global t
 | 
			
		||||
  (if dired-async-mode
 | 
			
		||||
      (if (fboundp 'advice-add)
 | 
			
		||||
          (progn (advice-add 'dired-create-files :override #'dired-async-create-files)
 | 
			
		||||
                 (advice-add 'wdired-do-renames :around #'dired-async-wdired-do-renames))
 | 
			
		||||
        (ad-activate 'dired-create-files)
 | 
			
		||||
        (ad-activate 'wdired-do-renames))
 | 
			
		||||
    (if (fboundp 'advice-remove)
 | 
			
		||||
        (progn (advice-remove 'dired-create-files #'dired-async-create-files)
 | 
			
		||||
               (advice-remove 'wdired-do-renames #'dired-async-wdired-do-renames))
 | 
			
		||||
      (ad-deactivate 'dired-create-files)
 | 
			
		||||
      (ad-deactivate 'wdired-do-renames))))
 | 
			
		||||
 | 
			
		||||
(defmacro dired-async--with-async-create-files (&rest body)
 | 
			
		||||
  "Evaluate BODY with ‘dired-create-files’ set to ‘dired-async-create-files’."
 | 
			
		||||
  (declare (indent 0))
 | 
			
		||||
  `(cl-letf (((symbol-function 'dired-create-files) #'dired-async-create-files))
 | 
			
		||||
     ,@body))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun dired-async-do-copy (&optional arg)
 | 
			
		||||
  "Run ‘dired-do-copy’ asynchronously."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (dired-async--with-async-create-files
 | 
			
		||||
   (dired-do-copy arg)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun dired-async-do-symlink (&optional arg)
 | 
			
		||||
  "Run ‘dired-do-symlink’ asynchronously."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (dired-async--with-async-create-files
 | 
			
		||||
   (dired-do-symlink arg)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun dired-async-do-hardlink (&optional arg)
 | 
			
		||||
  "Run ‘dired-do-hardlink’ asynchronously."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (dired-async--with-async-create-files
 | 
			
		||||
   (dired-do-hardlink arg)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun dired-async-do-rename (&optional arg)
 | 
			
		||||
  "Run ‘dired-do-rename’ asynchronously."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (dired-async--with-async-create-files
 | 
			
		||||
   (dired-do-rename arg)))
 | 
			
		||||
 | 
			
		||||
(provide 'dired-async)
 | 
			
		||||
 | 
			
		||||
;;; dired-async.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,73 +0,0 @@
 | 
			
		||||
;;; smtpmail-async.el --- Send e-mail with smtpmail.el asynchronously -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
 | 
			
		||||
 | 
			
		||||
;; Author: John Wiegley <jwiegley@gmail.com>
 | 
			
		||||
;; Created: 18 Jun 2012
 | 
			
		||||
 | 
			
		||||
;; Keywords: email async
 | 
			
		||||
;; X-URL: https://github.com/jwiegley/emacs-async
 | 
			
		||||
 | 
			
		||||
;; 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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
 | 
			
		||||
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
			
		||||
;; Boston, MA 02111-1307, USA.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Send e-mail with smtpmail.el asynchronously.  To use:
 | 
			
		||||
;;
 | 
			
		||||
;;   (require 'smtpmail-async)
 | 
			
		||||
;;
 | 
			
		||||
;;   (setq send-mail-function 'async-smtpmail-send-it
 | 
			
		||||
;;         message-send-mail-function 'async-smtpmail-send-it)
 | 
			
		||||
;;
 | 
			
		||||
;; This assumes you already have smtpmail.el working.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(defgroup smtpmail-async nil
 | 
			
		||||
  "Send e-mail with smtpmail.el asynchronously"
 | 
			
		||||
  :group 'smptmail)
 | 
			
		||||
 | 
			
		||||
(require 'async)
 | 
			
		||||
(require 'smtpmail)
 | 
			
		||||
(require 'message)
 | 
			
		||||
 | 
			
		||||
(defvar async-smtpmail-before-send-hook nil
 | 
			
		||||
  "Hook running in the child emacs in `async-smtpmail-send-it'.
 | 
			
		||||
It is called just before calling `smtpmail-send-it'.")
 | 
			
		||||
 | 
			
		||||
(defun async-smtpmail-send-it ()
 | 
			
		||||
  (let ((to          (message-field-value "To"))
 | 
			
		||||
        (buf-content (buffer-substring-no-properties
 | 
			
		||||
                      (point-min) (point-max))))
 | 
			
		||||
    (message "Delivering message to %s..." to)
 | 
			
		||||
    (async-start
 | 
			
		||||
     `(lambda ()
 | 
			
		||||
        (require 'smtpmail)
 | 
			
		||||
        (with-temp-buffer
 | 
			
		||||
          (insert ,buf-content)
 | 
			
		||||
          (set-buffer-multibyte nil)
 | 
			
		||||
          ;; Pass in the variable environment for smtpmail
 | 
			
		||||
          ,(async-inject-variables
 | 
			
		||||
            "\\`\\(smtpmail\\|async-smtpmail\\|\\(user-\\)?mail\\)-\\|auth-sources\\|epg\\|nsm"
 | 
			
		||||
            nil "\\`\\(mail-header-format-function\\|smtpmail-address-buffer\\|mail-mode-abbrev-table\\)")
 | 
			
		||||
          (run-hooks 'async-smtpmail-before-send-hook)
 | 
			
		||||
          (smtpmail-send-it)))
 | 
			
		||||
     (lambda (&optional _ignore)
 | 
			
		||||
       (message "Delivering message to %s...done" to)))))
 | 
			
		||||
 | 
			
		||||
(provide 'smtpmail-async)
 | 
			
		||||
 | 
			
		||||
;;; smtpmail-async.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,86 +0,0 @@
 | 
			
		||||
;;; bind-key-autoloads.el --- automatically extracted autoloads
 | 
			
		||||
;;
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(add-to-list 'load-path (directory-file-name
 | 
			
		||||
                         (or (file-name-directory #$) (car load-path))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "bind-key" "bind-key.el" (0 0 0 0))
 | 
			
		||||
;;; Generated autoloads from bind-key.el
 | 
			
		||||
 | 
			
		||||
(autoload 'bind-key "bind-key" "\
 | 
			
		||||
Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
 | 
			
		||||
 | 
			
		||||
KEY-NAME may be a vector, in which case it is passed straight to
 | 
			
		||||
`define-key'. Or it may be a string to be interpreted as
 | 
			
		||||
spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of
 | 
			
		||||
`edmacro-mode' for details.
 | 
			
		||||
 | 
			
		||||
COMMAND must be an interactive function or lambda form.
 | 
			
		||||
 | 
			
		||||
KEYMAP, if present, should be a keymap variable or symbol.
 | 
			
		||||
For example:
 | 
			
		||||
 | 
			
		||||
  (bind-key \"M-h\" #'some-interactive-function my-mode-map)
 | 
			
		||||
 | 
			
		||||
  (bind-key \"M-h\" #'some-interactive-function 'my-mode-map)
 | 
			
		||||
 | 
			
		||||
If PREDICATE is non-nil, it is a form evaluated to determine when
 | 
			
		||||
a key should be bound. It must return non-nil in such cases.
 | 
			
		||||
Emacs can evaluate this form at any time that it does redisplay
 | 
			
		||||
or operates on menu data structures, so you should write it so it
 | 
			
		||||
can safely be called at any time.
 | 
			
		||||
 | 
			
		||||
\(fn KEY-NAME COMMAND &optional KEYMAP PREDICATE)" nil t)
 | 
			
		||||
 | 
			
		||||
(autoload 'unbind-key "bind-key" "\
 | 
			
		||||
Unbind the given KEY-NAME, within the KEYMAP (if specified).
 | 
			
		||||
See `bind-key' for more details.
 | 
			
		||||
 | 
			
		||||
\(fn KEY-NAME &optional KEYMAP)" nil t)
 | 
			
		||||
 | 
			
		||||
(autoload 'bind-key* "bind-key" "\
 | 
			
		||||
Similar to `bind-key', but overrides any mode-specific bindings.
 | 
			
		||||
 | 
			
		||||
\(fn KEY-NAME COMMAND &optional PREDICATE)" nil t)
 | 
			
		||||
 | 
			
		||||
(autoload 'bind-keys "bind-key" "\
 | 
			
		||||
Bind multiple keys at once.
 | 
			
		||||
 | 
			
		||||
Accepts keyword arguments:
 | 
			
		||||
:map MAP               - a keymap into which the keybindings should be
 | 
			
		||||
                         added
 | 
			
		||||
:prefix KEY            - prefix key for these bindings
 | 
			
		||||
:prefix-map MAP        - name of the prefix map that should be created
 | 
			
		||||
                         for these bindings
 | 
			
		||||
:prefix-docstring STR  - docstring for the prefix-map variable
 | 
			
		||||
:menu-name NAME        - optional menu string for prefix map
 | 
			
		||||
:filter FORM           - optional form to determine when bindings apply
 | 
			
		||||
 | 
			
		||||
The rest of the arguments are conses of keybinding string and a
 | 
			
		||||
function symbol (unquoted).
 | 
			
		||||
 | 
			
		||||
\(fn &rest ARGS)" nil t)
 | 
			
		||||
 | 
			
		||||
(autoload 'bind-keys* "bind-key" "\
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
\(fn &rest ARGS)" nil t)
 | 
			
		||||
 | 
			
		||||
(autoload 'describe-personal-keybindings "bind-key" "\
 | 
			
		||||
Display all the personal keybindings defined by `bind-key'.
 | 
			
		||||
 | 
			
		||||
\(fn)" t nil)
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "bind-key" '("compare-keybindings" "get-binding-description" "bind-key" "personal-keybindings" "override-global-m")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; version-control: never
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; no-update-autoloads: t
 | 
			
		||||
;; coding: utf-8
 | 
			
		||||
;; End:
 | 
			
		||||
;;; bind-key-autoloads.el ends here
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
;;; -*- no-byte-compile: t -*-
 | 
			
		||||
(define-package "bind-key" "20200805.1727" "A simple way to manage personal keybindings" 'nil :commit "4fb1f9a68f1e7e7d614652afc017a6652fd029f1" :keywords '("keys" "keybinding" "config" "dotemacs") :authors '(("John Wiegley" . "johnw@newartisans.com")) :maintainer '("John Wiegley" . "johnw@newartisans.com") :url "https://github.com/jwiegley/use-package")
 | 
			
		||||
@@ -1,459 +0,0 @@
 | 
			
		||||
;;; bind-key.el --- A simple way to manage personal keybindings
 | 
			
		||||
 | 
			
		||||
;; Copyright (c) 2012-2017 John Wiegley
 | 
			
		||||
 | 
			
		||||
;; Author: John Wiegley <johnw@newartisans.com>
 | 
			
		||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
 | 
			
		||||
;; Created: 16 Jun 2012
 | 
			
		||||
;; Modified: 29 Nov 2017
 | 
			
		||||
;; Version: 2.4
 | 
			
		||||
;; Package-Version: 20200805.1727
 | 
			
		||||
;; Package-Commit: 4fb1f9a68f1e7e7d614652afc017a6652fd029f1
 | 
			
		||||
;; Keywords: keys keybinding config dotemacs
 | 
			
		||||
;; URL: https://github.com/jwiegley/use-package
 | 
			
		||||
 | 
			
		||||
;; 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, 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 gnu emacs; see the file copying.  if not, write to the
 | 
			
		||||
;; free software foundation, inc., 59 temple place - suite 330,
 | 
			
		||||
;; boston, ma 02111-1307, usa.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; If you have lots of keybindings set in your .emacs file, it can be hard to
 | 
			
		||||
;; know which ones you haven't set yet, and which may now be overriding some
 | 
			
		||||
;; new default in a new emacs version.  This module aims to solve that
 | 
			
		||||
;; problem.
 | 
			
		||||
;;
 | 
			
		||||
;; Bind keys as follows in your .emacs:
 | 
			
		||||
;;
 | 
			
		||||
;;   (require 'bind-key)
 | 
			
		||||
;;
 | 
			
		||||
;;   (bind-key "C-c x" 'my-ctrl-c-x-command)
 | 
			
		||||
;;
 | 
			
		||||
;; If the keybinding argument is a vector, it is passed straight to
 | 
			
		||||
;; `define-key', so remapping a key with `[remap COMMAND]' works as
 | 
			
		||||
;; expected:
 | 
			
		||||
;;
 | 
			
		||||
;;   (bind-key [remap original-ctrl-c-x-command] 'my-ctrl-c-x-command)
 | 
			
		||||
;;
 | 
			
		||||
;; If you want the keybinding to override all minor modes that may also bind
 | 
			
		||||
;; the same key, use the `bind-key*' form:
 | 
			
		||||
;;
 | 
			
		||||
;;   (bind-key* "<C-return>" 'other-window)
 | 
			
		||||
;;
 | 
			
		||||
;; If you want to rebind a key only in a particular keymap, use:
 | 
			
		||||
;;
 | 
			
		||||
;;   (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
 | 
			
		||||
;;
 | 
			
		||||
;; To unbind a key within a keymap (for example, to stop your favorite major
 | 
			
		||||
;; mode from changing a binding that you don't want to override everywhere),
 | 
			
		||||
;; use `unbind-key':
 | 
			
		||||
;;
 | 
			
		||||
;;   (unbind-key "C-c x" some-other-mode-map)
 | 
			
		||||
;;
 | 
			
		||||
;; To bind multiple keys at once, or set up a prefix map, a `bind-keys' macro
 | 
			
		||||
;; is provided.  It accepts keyword arguments, please see its documentation
 | 
			
		||||
;; for a detailed description.
 | 
			
		||||
;;
 | 
			
		||||
;; To add keys into a specific map, use :map argument
 | 
			
		||||
;;
 | 
			
		||||
;;    (bind-keys :map dired-mode-map
 | 
			
		||||
;;               ("o" . dired-omit-mode)
 | 
			
		||||
;;               ("a" . some-custom-dired-function))
 | 
			
		||||
;;
 | 
			
		||||
;; To set up a prefix map, use `:prefix-map' and `:prefix' arguments (both are
 | 
			
		||||
;; required)
 | 
			
		||||
;;
 | 
			
		||||
;;    (bind-keys :prefix-map my-customize-prefix-map
 | 
			
		||||
;;               :prefix "C-c c"
 | 
			
		||||
;;               ("f" . customize-face)
 | 
			
		||||
;;               ("v" . customize-variable))
 | 
			
		||||
;;
 | 
			
		||||
;; You can combine all the keywords together.  Additionally,
 | 
			
		||||
;; `:prefix-docstring' can be specified to set documentation of created
 | 
			
		||||
;; `:prefix-map' variable.
 | 
			
		||||
;;
 | 
			
		||||
;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
 | 
			
		||||
;; will not be overridden by other modes), you may use `bind-keys*' macro:
 | 
			
		||||
;;
 | 
			
		||||
;;    (bind-keys*
 | 
			
		||||
;;     ("C-o" . other-window)
 | 
			
		||||
;;     ("C-M-n" . forward-page)
 | 
			
		||||
;;     ("C-M-p" . backward-page))
 | 
			
		||||
;;
 | 
			
		||||
;; After Emacs loads, you can see a summary of all your personal keybindings
 | 
			
		||||
;; currently in effect with this command:
 | 
			
		||||
;;
 | 
			
		||||
;;   M-x describe-personal-keybindings
 | 
			
		||||
;;
 | 
			
		||||
;; This display will tell you if you've overridden a default keybinding, and
 | 
			
		||||
;; what the default was.  Also, it will tell you if the key was rebound after
 | 
			
		||||
;; your binding it with `bind-key', and what it was rebound it to.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(require 'easy-mmode)
 | 
			
		||||
 | 
			
		||||
(defgroup bind-key nil
 | 
			
		||||
  "A simple way to manage personal keybindings"
 | 
			
		||||
  :group 'emacs)
 | 
			
		||||
 | 
			
		||||
(defcustom bind-key-column-widths '(18 . 40)
 | 
			
		||||
  "Width of columns in `describe-personal-keybindings'."
 | 
			
		||||
  :type '(cons integer integer)
 | 
			
		||||
  :group 'bind-key)
 | 
			
		||||
 | 
			
		||||
(defcustom bind-key-segregation-regexp
 | 
			
		||||
  "\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
 | 
			
		||||
  "Regular expression used to divide key sets in the output from
 | 
			
		||||
\\[describe-personal-keybindings]."
 | 
			
		||||
  :type 'regexp
 | 
			
		||||
  :group 'bind-key)
 | 
			
		||||
 | 
			
		||||
(defcustom bind-key-describe-special-forms nil
 | 
			
		||||
  "If non-nil, extract docstrings from lambdas, closures and keymaps if possible."
 | 
			
		||||
  :type 'boolean
 | 
			
		||||
  :group 'bind-key)
 | 
			
		||||
 | 
			
		||||
;; Create override-global-mode to force key remappings
 | 
			
		||||
 | 
			
		||||
(defvar override-global-map (make-keymap)
 | 
			
		||||
  "override-global-mode keymap")
 | 
			
		||||
 | 
			
		||||
(define-minor-mode override-global-mode
 | 
			
		||||
  "A minor mode so that keymap settings override other modes."
 | 
			
		||||
  t "")
 | 
			
		||||
 | 
			
		||||
;; the keymaps in `emulation-mode-map-alists' take precedence over
 | 
			
		||||
;; `minor-mode-map-alist'
 | 
			
		||||
(add-to-list 'emulation-mode-map-alists
 | 
			
		||||
             `((override-global-mode . ,override-global-map)))
 | 
			
		||||
 | 
			
		||||
(defvar personal-keybindings nil
 | 
			
		||||
  "List of bindings performed by `bind-key'.
 | 
			
		||||
 | 
			
		||||
Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defmacro bind-key (key-name command &optional keymap predicate)
 | 
			
		||||
  "Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
 | 
			
		||||
 | 
			
		||||
KEY-NAME may be a vector, in which case it is passed straight to
 | 
			
		||||
`define-key'. Or it may be a string to be interpreted as
 | 
			
		||||
spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of
 | 
			
		||||
`edmacro-mode' for details.
 | 
			
		||||
 | 
			
		||||
COMMAND must be an interactive function or lambda form.
 | 
			
		||||
 | 
			
		||||
KEYMAP, if present, should be a keymap variable or symbol.
 | 
			
		||||
For example:
 | 
			
		||||
 | 
			
		||||
  (bind-key \"M-h\" #'some-interactive-function my-mode-map)
 | 
			
		||||
 | 
			
		||||
  (bind-key \"M-h\" #'some-interactive-function 'my-mode-map)
 | 
			
		||||
 | 
			
		||||
If PREDICATE is non-nil, it is a form evaluated to determine when
 | 
			
		||||
a key should be bound. It must return non-nil in such cases.
 | 
			
		||||
Emacs can evaluate this form at any time that it does redisplay
 | 
			
		||||
or operates on menu data structures, so you should write it so it
 | 
			
		||||
can safely be called at any time."
 | 
			
		||||
  (let ((namevar (make-symbol "name"))
 | 
			
		||||
        (keyvar (make-symbol "key"))
 | 
			
		||||
        (kdescvar (make-symbol "kdesc"))
 | 
			
		||||
        (bindingvar (make-symbol "binding")))
 | 
			
		||||
    `(let* ((,namevar ,key-name)
 | 
			
		||||
            (,keyvar (if (vectorp ,namevar) ,namevar
 | 
			
		||||
                       (read-kbd-macro ,namevar)))
 | 
			
		||||
            (kmap (if (and ,keymap (symbolp ,keymap)) (symbol-value ,keymap) ,keymap))
 | 
			
		||||
            (,kdescvar (cons (if (stringp ,namevar) ,namevar
 | 
			
		||||
                               (key-description ,namevar))
 | 
			
		||||
                             (if (symbolp ,keymap) ,keymap (quote ,keymap))))
 | 
			
		||||
            (,bindingvar (lookup-key (or kmap global-map) ,keyvar)))
 | 
			
		||||
       (let ((entry (assoc ,kdescvar personal-keybindings))
 | 
			
		||||
             (details (list ,command
 | 
			
		||||
                            (unless (numberp ,bindingvar)
 | 
			
		||||
                              ,bindingvar))))
 | 
			
		||||
         (if entry
 | 
			
		||||
             (setcdr entry details)
 | 
			
		||||
           (add-to-list 'personal-keybindings (cons ,kdescvar details))))
 | 
			
		||||
       ,(if predicate
 | 
			
		||||
            `(define-key (or kmap global-map) ,keyvar
 | 
			
		||||
               '(menu-item "" nil :filter (lambda (&optional _)
 | 
			
		||||
                                            (when ,predicate
 | 
			
		||||
                                              ,command))))
 | 
			
		||||
          `(define-key (or kmap global-map) ,keyvar ,command)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defmacro unbind-key (key-name &optional keymap)
 | 
			
		||||
  "Unbind the given KEY-NAME, within the KEYMAP (if specified).
 | 
			
		||||
See `bind-key' for more details."
 | 
			
		||||
  `(progn
 | 
			
		||||
     (bind-key ,key-name nil ,keymap)
 | 
			
		||||
     (setq personal-keybindings
 | 
			
		||||
           (cl-delete-if #'(lambda (k)
 | 
			
		||||
                             ,(if keymap
 | 
			
		||||
                                  `(and (consp (car k))
 | 
			
		||||
                                        (string= (caar k) ,key-name)
 | 
			
		||||
                                        (eq (cdar k) ',keymap))
 | 
			
		||||
                                `(and (stringp (car k))
 | 
			
		||||
                                      (string= (car k) ,key-name))))
 | 
			
		||||
                         personal-keybindings))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defmacro bind-key* (key-name command &optional predicate)
 | 
			
		||||
  "Similar to `bind-key', but overrides any mode-specific bindings."
 | 
			
		||||
  `(bind-key ,key-name ,command override-global-map ,predicate))
 | 
			
		||||
 | 
			
		||||
(defun bind-keys-form (args keymap)
 | 
			
		||||
  "Bind multiple keys at once.
 | 
			
		||||
 | 
			
		||||
Accepts keyword arguments:
 | 
			
		||||
:map MAP               - a keymap into which the keybindings should be
 | 
			
		||||
                         added
 | 
			
		||||
:prefix KEY            - prefix key for these bindings
 | 
			
		||||
:prefix-map MAP        - name of the prefix map that should be created
 | 
			
		||||
                         for these bindings
 | 
			
		||||
:prefix-docstring STR  - docstring for the prefix-map variable
 | 
			
		||||
:menu-name NAME        - optional menu string for prefix map
 | 
			
		||||
:filter FORM           - optional form to determine when bindings apply
 | 
			
		||||
 | 
			
		||||
The rest of the arguments are conses of keybinding string and a
 | 
			
		||||
function symbol (unquoted)."
 | 
			
		||||
  (let (map
 | 
			
		||||
        doc
 | 
			
		||||
        prefix-map
 | 
			
		||||
        prefix
 | 
			
		||||
        filter
 | 
			
		||||
        menu-name
 | 
			
		||||
        pkg)
 | 
			
		||||
 | 
			
		||||
    ;; Process any initial keyword arguments
 | 
			
		||||
    (let ((cont t))
 | 
			
		||||
      (while (and cont args)
 | 
			
		||||
        (if (cond ((and (eq :map (car args))
 | 
			
		||||
                        (not prefix-map))
 | 
			
		||||
                   (setq map (cadr args)))
 | 
			
		||||
                  ((eq :prefix-docstring (car args))
 | 
			
		||||
                   (setq doc (cadr args)))
 | 
			
		||||
                  ((and (eq :prefix-map (car args))
 | 
			
		||||
                        (not (memq map '(global-map
 | 
			
		||||
                                         override-global-map))))
 | 
			
		||||
                   (setq prefix-map (cadr args)))
 | 
			
		||||
                  ((eq :prefix (car args))
 | 
			
		||||
                   (setq prefix (cadr args)))
 | 
			
		||||
                  ((eq :filter (car args))
 | 
			
		||||
                   (setq filter (cadr args)) t)
 | 
			
		||||
                  ((eq :menu-name (car args))
 | 
			
		||||
                   (setq menu-name (cadr args)))
 | 
			
		||||
                  ((eq :package (car args))
 | 
			
		||||
                   (setq pkg (cadr args))))
 | 
			
		||||
            (setq args (cddr args))
 | 
			
		||||
          (setq cont nil))))
 | 
			
		||||
 | 
			
		||||
    (when (or (and prefix-map (not prefix))
 | 
			
		||||
              (and prefix (not prefix-map)))
 | 
			
		||||
      (error "Both :prefix-map and :prefix must be supplied"))
 | 
			
		||||
 | 
			
		||||
    (when (and menu-name (not prefix))
 | 
			
		||||
      (error "If :menu-name is supplied, :prefix must be too"))
 | 
			
		||||
 | 
			
		||||
    (unless map (setq map keymap))
 | 
			
		||||
 | 
			
		||||
    ;; Process key binding arguments
 | 
			
		||||
    (let (first next)
 | 
			
		||||
      (while args
 | 
			
		||||
        (if (keywordp (car args))
 | 
			
		||||
            (progn
 | 
			
		||||
              (setq next args)
 | 
			
		||||
              (setq args nil))
 | 
			
		||||
          (if first
 | 
			
		||||
              (nconc first (list (car args)))
 | 
			
		||||
            (setq first (list (car args))))
 | 
			
		||||
          (setq args (cdr args))))
 | 
			
		||||
 | 
			
		||||
      (cl-flet
 | 
			
		||||
          ((wrap (map bindings)
 | 
			
		||||
                 (if (and map pkg (not (memq map '(global-map
 | 
			
		||||
                                                   override-global-map))))
 | 
			
		||||
                     `((if (boundp ',map)
 | 
			
		||||
                           ,(macroexp-progn bindings)
 | 
			
		||||
                         (eval-after-load
 | 
			
		||||
                             ,(if (symbolp pkg) `',pkg pkg)
 | 
			
		||||
                           ',(macroexp-progn bindings))))
 | 
			
		||||
                   bindings)))
 | 
			
		||||
 | 
			
		||||
        (append
 | 
			
		||||
         (when prefix-map
 | 
			
		||||
           `((defvar ,prefix-map)
 | 
			
		||||
             ,@(when doc `((put ',prefix-map 'variable-documentation ,doc)))
 | 
			
		||||
             ,@(if menu-name
 | 
			
		||||
                   `((define-prefix-command ',prefix-map nil ,menu-name))
 | 
			
		||||
                 `((define-prefix-command ',prefix-map)))
 | 
			
		||||
             ,@(if (and map (not (eq map 'global-map)))
 | 
			
		||||
                   (wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
 | 
			
		||||
                 `((bind-key ,prefix ',prefix-map nil ,filter)))))
 | 
			
		||||
         (wrap map
 | 
			
		||||
               (cl-mapcan
 | 
			
		||||
                (lambda (form)
 | 
			
		||||
                  (let ((fun (and (cdr form) (list 'function (cdr form)))))
 | 
			
		||||
                    (if prefix-map
 | 
			
		||||
                        `((bind-key ,(car form) ,fun ,prefix-map ,filter))
 | 
			
		||||
                      (if (and map (not (eq map 'global-map)))
 | 
			
		||||
                          `((bind-key ,(car form) ,fun ,map ,filter))
 | 
			
		||||
                        `((bind-key ,(car form) ,fun nil ,filter))))))
 | 
			
		||||
                first))
 | 
			
		||||
         (when next
 | 
			
		||||
           (bind-keys-form (if pkg
 | 
			
		||||
                               (cons :package (cons pkg next))
 | 
			
		||||
                             next) map)))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defmacro bind-keys (&rest args)
 | 
			
		||||
  "Bind multiple keys at once.
 | 
			
		||||
 | 
			
		||||
Accepts keyword arguments:
 | 
			
		||||
:map MAP               - a keymap into which the keybindings should be
 | 
			
		||||
                         added
 | 
			
		||||
:prefix KEY            - prefix key for these bindings
 | 
			
		||||
:prefix-map MAP        - name of the prefix map that should be created
 | 
			
		||||
                         for these bindings
 | 
			
		||||
:prefix-docstring STR  - docstring for the prefix-map variable
 | 
			
		||||
:menu-name NAME        - optional menu string for prefix map
 | 
			
		||||
:filter FORM           - optional form to determine when bindings apply
 | 
			
		||||
 | 
			
		||||
The rest of the arguments are conses of keybinding string and a
 | 
			
		||||
function symbol (unquoted)."
 | 
			
		||||
  (macroexp-progn (bind-keys-form args nil)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defmacro bind-keys* (&rest args)
 | 
			
		||||
  (macroexp-progn (bind-keys-form args 'override-global-map)))
 | 
			
		||||
 | 
			
		||||
(defun get-binding-description (elem)
 | 
			
		||||
  (cond
 | 
			
		||||
   ((listp elem)
 | 
			
		||||
    (cond
 | 
			
		||||
     ((memq (car elem) '(lambda function))
 | 
			
		||||
      (if (and bind-key-describe-special-forms
 | 
			
		||||
               (stringp (nth 2 elem)))
 | 
			
		||||
          (nth 2 elem)
 | 
			
		||||
        "#<lambda>"))
 | 
			
		||||
     ((eq 'closure (car elem))
 | 
			
		||||
      (if (and bind-key-describe-special-forms
 | 
			
		||||
               (stringp (nth 3 elem)))
 | 
			
		||||
          (nth 3 elem)
 | 
			
		||||
        "#<closure>"))
 | 
			
		||||
     ((eq 'keymap (car elem))
 | 
			
		||||
      "#<keymap>")
 | 
			
		||||
     (t
 | 
			
		||||
      elem)))
 | 
			
		||||
   ;; must be a symbol, non-symbol keymap case covered above
 | 
			
		||||
   ((and bind-key-describe-special-forms (keymapp elem))
 | 
			
		||||
    (let ((doc (get elem 'variable-documentation)))
 | 
			
		||||
      (if (stringp doc) doc elem)))
 | 
			
		||||
   ((symbolp elem)
 | 
			
		||||
    elem)
 | 
			
		||||
   (t
 | 
			
		||||
    "#<byte-compiled lambda>")))
 | 
			
		||||
 | 
			
		||||
(defun compare-keybindings (l r)
 | 
			
		||||
  (let* ((regex bind-key-segregation-regexp)
 | 
			
		||||
         (lgroup (and (string-match regex (caar l))
 | 
			
		||||
                      (match-string 0 (caar l))))
 | 
			
		||||
         (rgroup (and (string-match regex (caar r))
 | 
			
		||||
                      (match-string 0 (caar r))))
 | 
			
		||||
         (lkeymap (cdar l))
 | 
			
		||||
         (rkeymap (cdar r)))
 | 
			
		||||
    (cond
 | 
			
		||||
     ((and (null lkeymap) rkeymap)
 | 
			
		||||
      (cons t t))
 | 
			
		||||
     ((and lkeymap (null rkeymap))
 | 
			
		||||
      (cons nil t))
 | 
			
		||||
     ((and lkeymap rkeymap
 | 
			
		||||
           (not (string= (symbol-name lkeymap) (symbol-name rkeymap))))
 | 
			
		||||
      (cons (string< (symbol-name lkeymap) (symbol-name rkeymap)) t))
 | 
			
		||||
     ((and (null lgroup) rgroup)
 | 
			
		||||
      (cons t t))
 | 
			
		||||
     ((and lgroup (null rgroup))
 | 
			
		||||
      (cons nil t))
 | 
			
		||||
     ((and lgroup rgroup)
 | 
			
		||||
      (if (string= lgroup rgroup)
 | 
			
		||||
          (cons (string< (caar l) (caar r)) nil)
 | 
			
		||||
        (cons (string< lgroup rgroup) t)))
 | 
			
		||||
     (t
 | 
			
		||||
      (cons (string< (caar l) (caar r)) nil)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun describe-personal-keybindings ()
 | 
			
		||||
  "Display all the personal keybindings defined by `bind-key'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (with-output-to-temp-buffer "*Personal Keybindings*"
 | 
			
		||||
    (princ (format (concat "Key name%s Command%s Comments\n%s %s "
 | 
			
		||||
                           "---------------------\n")
 | 
			
		||||
                   (make-string (- (car bind-key-column-widths) 9) ? )
 | 
			
		||||
                   (make-string (- (cdr bind-key-column-widths) 8) ? )
 | 
			
		||||
                   (make-string (1- (car bind-key-column-widths)) ?-)
 | 
			
		||||
                   (make-string (1- (cdr bind-key-column-widths)) ?-)))
 | 
			
		||||
    (let (last-binding)
 | 
			
		||||
      (dolist (binding
 | 
			
		||||
               (setq personal-keybindings
 | 
			
		||||
                     (sort personal-keybindings
 | 
			
		||||
                           (lambda (l r)
 | 
			
		||||
                             (car (compare-keybindings l r))))))
 | 
			
		||||
 | 
			
		||||
        (if (not (eq (cdar last-binding) (cdar binding)))
 | 
			
		||||
            (princ (format "\n\n%s: %s\n%s\n\n"
 | 
			
		||||
                           (cdar binding) (caar binding)
 | 
			
		||||
                           (make-string (+ 21 (car bind-key-column-widths)
 | 
			
		||||
                                           (cdr bind-key-column-widths)) ?-)))
 | 
			
		||||
          (if (and last-binding
 | 
			
		||||
                   (cdr (compare-keybindings last-binding binding)))
 | 
			
		||||
              (princ "\n")))
 | 
			
		||||
 | 
			
		||||
        (let* ((key-name (caar binding))
 | 
			
		||||
               (at-present (lookup-key (or (symbol-value (cdar binding))
 | 
			
		||||
                                           (current-global-map))
 | 
			
		||||
                                       (read-kbd-macro key-name)))
 | 
			
		||||
               (command (nth 1 binding))
 | 
			
		||||
               (was-command (nth 2 binding))
 | 
			
		||||
               (command-desc (get-binding-description command))
 | 
			
		||||
               (was-command-desc (and was-command
 | 
			
		||||
                                      (get-binding-description was-command)))
 | 
			
		||||
               (at-present-desc (get-binding-description at-present))
 | 
			
		||||
               )
 | 
			
		||||
          (let ((line
 | 
			
		||||
                 (format
 | 
			
		||||
                  (format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths)
 | 
			
		||||
                          (cdr bind-key-column-widths))
 | 
			
		||||
                  key-name (format "`%s\'" command-desc)
 | 
			
		||||
                  (if (string= command-desc at-present-desc)
 | 
			
		||||
                      (if (or (null was-command)
 | 
			
		||||
                              (string= command-desc was-command-desc))
 | 
			
		||||
                          ""
 | 
			
		||||
                        (format "was `%s\'" was-command-desc))
 | 
			
		||||
                    (format "[now: `%s\']" at-present)))))
 | 
			
		||||
            (princ (if (string-match "[ \t]+\n" line)
 | 
			
		||||
                       (replace-match "\n" t t line)
 | 
			
		||||
                     line))))
 | 
			
		||||
 | 
			
		||||
        (setq last-binding binding)))))
 | 
			
		||||
 | 
			
		||||
(provide 'bind-key)
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
 | 
			
		||||
;; indent-tabs-mode: nil
 | 
			
		||||
;; End:
 | 
			
		||||
 | 
			
		||||
;;; bind-key.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,26 +0,0 @@
 | 
			
		||||
;;; dash-autoloads.el --- automatically extracted autoloads
 | 
			
		||||
;;
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(add-to-list 'load-path (directory-file-name
 | 
			
		||||
                         (or (file-name-directory #$) (car load-path))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "dash" "dash.el" (0 0 0 0))
 | 
			
		||||
;;; Generated autoloads from dash.el
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dash" '("dash-" "-keep" "-butlast" "-non" "-only-some" "-zip" "-e" "->" "-a" "-gr" "-when-let" "-d" "-l" "-s" "-p" "-r" "-m" "-i" "-f" "-u" "-value-to-list" "-t" "--" "-c" "!cons" "!cdr")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil nil ("dash-pkg.el") (0 0 0 0))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; version-control: never
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; no-update-autoloads: t
 | 
			
		||||
;; coding: utf-8
 | 
			
		||||
;; End:
 | 
			
		||||
;;; dash-autoloads.el ends here
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
(define-package "dash" "20200803.1520" "A modern list library for Emacs" 'nil :commit "b92ab5a39b987e4fe69317b9d9fda452300baf20" :keywords
 | 
			
		||||
  '("lists")
 | 
			
		||||
  :authors
 | 
			
		||||
  '(("Magnar Sveen" . "magnars@gmail.com"))
 | 
			
		||||
  :maintainer
 | 
			
		||||
  '("Magnar Sveen" . "magnars@gmail.com"))
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; End:
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,18 +0,0 @@
 | 
			
		||||
This is the file .../info/dir, which contains the
 | 
			
		||||
topmost node of the Info hierarchy, called (dir)Top.
 | 
			
		||||
The first time you invoke Info you start off looking at this node.
 | 
			
		||||
 | 
			
		||||
File: dir,	Node: Top	This is the top of the INFO tree
 | 
			
		||||
 | 
			
		||||
  This (the Directory node) gives a menu of major topics.
 | 
			
		||||
  Typing "q" exits, "H" lists all Info commands, "d" returns here,
 | 
			
		||||
  "h" gives a primer for first-timers,
 | 
			
		||||
  "mEmacs<Return>" visits the Emacs manual, etc.
 | 
			
		||||
 | 
			
		||||
  In Emacs, you can click mouse button 2 on a menu item or cross reference
 | 
			
		||||
  to select it.
 | 
			
		||||
 | 
			
		||||
* Menu:
 | 
			
		||||
 | 
			
		||||
Emacs
 | 
			
		||||
* Dash: (dash.info).            A modern list library for GNU Emacs
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
;;; dracula-theme-autoloads.el --- automatically extracted autoloads
 | 
			
		||||
;;
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(add-to-list 'load-path (directory-file-name
 | 
			
		||||
                         (or (file-name-directory #$) (car load-path))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "dracula-theme" "dracula-theme.el" (0 0 0 0))
 | 
			
		||||
;;; Generated autoloads from dracula-theme.el
 | 
			
		||||
 | 
			
		||||
(when load-file-name (add-to-list 'custom-theme-load-path (file-name-as-directory (file-name-directory load-file-name))))
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dracula-theme" '("dracula-")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil nil ("dracula-theme-pkg.el" "test-profile.el")
 | 
			
		||||
;;;;;;  (0 0 0 0))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; version-control: never
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; no-update-autoloads: t
 | 
			
		||||
;; coding: utf-8
 | 
			
		||||
;; End:
 | 
			
		||||
;;; dracula-theme-autoloads.el ends here
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
(define-package "dracula-theme" "20200814.1717" "Dracula Theme"
 | 
			
		||||
  '((emacs "24.3"))
 | 
			
		||||
  :commit "3b7c2905d249f47bc9c09d304c16f72f217df2e0" :authors
 | 
			
		||||
  '(("film42"))
 | 
			
		||||
  :maintainer
 | 
			
		||||
  '("film42")
 | 
			
		||||
  :url "https://github.com/dracula/emacs")
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; End:
 | 
			
		||||
@@ -1,742 +0,0 @@
 | 
			
		||||
;;; dracula-theme.el --- Dracula Theme
 | 
			
		||||
 | 
			
		||||
;; Copyright 2015-present, All rights reserved
 | 
			
		||||
;;
 | 
			
		||||
;; Code licensed under the MIT license
 | 
			
		||||
 | 
			
		||||
;; Author: film42
 | 
			
		||||
;; Version: 1.7.0
 | 
			
		||||
;; Package-Requires: ((emacs "24.3"))
 | 
			
		||||
;; URL: https://github.com/dracula/emacs
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; A dark color theme available for a number of editors.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(deftheme dracula)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;; Configuration options:
 | 
			
		||||
 | 
			
		||||
(defgroup dracula nil
 | 
			
		||||
  "Dracula theme options.
 | 
			
		||||
 | 
			
		||||
The theme has to be reloaded after changing anything in this group."
 | 
			
		||||
  :group 'faces)
 | 
			
		||||
 | 
			
		||||
(defcustom dracula-enlarge-headings t
 | 
			
		||||
  "Use different font sizes for some headings and titles."
 | 
			
		||||
  :type 'boolean
 | 
			
		||||
  :group 'dracula)
 | 
			
		||||
 | 
			
		||||
(defcustom dracula-height-title-1 1.3
 | 
			
		||||
  "Font size 100%."
 | 
			
		||||
  :type 'number
 | 
			
		||||
  :group 'dracula)
 | 
			
		||||
 | 
			
		||||
(defcustom dracula-height-title-2 1.1
 | 
			
		||||
  "Font size 110%."
 | 
			
		||||
  :type 'number
 | 
			
		||||
  :group 'dracula)
 | 
			
		||||
 | 
			
		||||
(defcustom dracula-height-title-3 1.0
 | 
			
		||||
  "Font size 130%."
 | 
			
		||||
  :type 'number
 | 
			
		||||
  :group 'dracula)
 | 
			
		||||
 | 
			
		||||
(defcustom dracula-height-doc-title 1.44
 | 
			
		||||
  "Font size 144%."
 | 
			
		||||
  :type 'number
 | 
			
		||||
  :group 'dracula)
 | 
			
		||||
 | 
			
		||||
(defcustom dracula-alternate-mode-line-and-minibuffer nil
 | 
			
		||||
  "Use less bold and pink in the minibuffer."
 | 
			
		||||
  :type 'boolean
 | 
			
		||||
  :group 'dracula)
 | 
			
		||||
 | 
			
		||||
(defvar dracula-use-24-bit-colors-on-256-colors-terms nil
 | 
			
		||||
  "Use true colors even on terminals announcing less capabilities.
 | 
			
		||||
 | 
			
		||||
Beware the use of this variable.  Using it may lead to unwanted
 | 
			
		||||
behavior, the most common one being an ugly blue background on
 | 
			
		||||
terminals, which don't understand 24 bit colors.  To avoid this
 | 
			
		||||
blue background, when using this variable, one can try to add the
 | 
			
		||||
following lines in their config file after having load the
 | 
			
		||||
Dracula theme:
 | 
			
		||||
 | 
			
		||||
    (unless (display-graphic-p)
 | 
			
		||||
      (set-face-background 'default \"black\" nil))
 | 
			
		||||
 | 
			
		||||
There is a lot of discussion behind the 256 colors theme (see URL
 | 
			
		||||
`https://github.com/dracula/emacs/pull/57').  Please take time to
 | 
			
		||||
read it before opening a new issue about your will.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;; Theme definition:
 | 
			
		||||
 | 
			
		||||
;; Assigment form: VARIABLE COLOR [256-COLOR [TTY-COLOR]]
 | 
			
		||||
(let ((colors '(;; Upstream theme color
 | 
			
		||||
                (dracula-bg      "#282a36" "unspecified-bg" "unspecified-bg") ; official background
 | 
			
		||||
                (dracula-fg      "#f8f8f2" "#ffffff" "brightwhite") ; official foreground
 | 
			
		||||
                (dracula-current "#44475a" "#303030" "brightblack") ; official current-line/selection
 | 
			
		||||
                (dracula-comment "#6272a4" "#5f5faf" "blue")        ; official comment
 | 
			
		||||
                (dracula-cyan    "#8be9fd" "#87d7ff" "brightcyan")  ; official cyan
 | 
			
		||||
                (dracula-green   "#50fa7b" "#5fff87" "green")       ; official green
 | 
			
		||||
                (dracula-orange  "#ffb86c" "#ffaf5f" "brightred")   ; official orange
 | 
			
		||||
                (dracula-pink    "#ff79c6" "#ff87d7" "magenta")     ; official pink
 | 
			
		||||
                (dracula-purple  "#bd93f9" "#af87ff" "brightmagenta") ; official purple
 | 
			
		||||
                (dracula-red     "#ff5555" "#ff8787" "red")         ; official red
 | 
			
		||||
                (dracula-yellow  "#f1fa8c" "#ffff87" "yellow")      ; official yellow
 | 
			
		||||
                ;; Other colors
 | 
			
		||||
                (bg2             "#373844" "#121212" "brightblack")
 | 
			
		||||
                (bg3             "#464752" "#262626" "brightblack")
 | 
			
		||||
                (bg4             "#565761" "#444444" "brightblack")
 | 
			
		||||
                (fg2             "#e2e2dc" "#e4e4e4" "brightwhite")
 | 
			
		||||
                (fg3             "#ccccc7" "#c6c6c6" "white")
 | 
			
		||||
                (fg4             "#b6b6b2" "#b2b2b2" "white")
 | 
			
		||||
                (other-blue      "#0189cc" "#0087ff" "brightblue")))
 | 
			
		||||
      (faces '(;; default
 | 
			
		||||
               (cursor :background ,fg3)
 | 
			
		||||
               (completions-first-difference :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (default :background ,dracula-bg :foreground ,dracula-fg)
 | 
			
		||||
               (default-italic :slant italic)
 | 
			
		||||
               (ffap :foreground ,fg4)
 | 
			
		||||
               (fringe :background ,dracula-bg :foreground ,fg4)
 | 
			
		||||
               (highlight :foreground ,fg3 :background ,bg3)
 | 
			
		||||
               (hl-line :background ,dracula-current :extend t)
 | 
			
		||||
               (info-quoted-name :foreground ,dracula-orange)
 | 
			
		||||
               (info-string :foreground ,dracula-yellow)
 | 
			
		||||
               (lazy-highlight :foreground ,fg2 :background ,bg2)
 | 
			
		||||
               (link :foreground ,dracula-cyan :underline t)
 | 
			
		||||
               (linum :slant italic :foreground ,bg4 :background ,dracula-bg)
 | 
			
		||||
               (line-number :slant italic :foreground ,bg4 :background ,dracula-bg)
 | 
			
		||||
               (match :background ,dracula-yellow :foreground ,dracula-bg)
 | 
			
		||||
               (minibuffer-prompt
 | 
			
		||||
                ,@(if dracula-alternate-mode-line-and-minibuffer
 | 
			
		||||
                      (list :weight 'normal :foreground dracula-fg)
 | 
			
		||||
                    (list :weight 'bold :foreground dracula-pink)))
 | 
			
		||||
               (read-multiple-choice-face :inherit completions-first-difference)
 | 
			
		||||
               (region :inherit match :extend t)
 | 
			
		||||
               (trailing-whitespace :foreground "unspecified-fg" :background ,dracula-orange)
 | 
			
		||||
               (vertical-border :foreground ,bg2)
 | 
			
		||||
               (success :foreground ,dracula-green)
 | 
			
		||||
               (warning :foreground ,dracula-orange)
 | 
			
		||||
               (error :foreground ,dracula-red)
 | 
			
		||||
               (header-line :background ,dracula-bg)
 | 
			
		||||
               ;; syntax
 | 
			
		||||
               (font-lock-builtin-face :foreground ,dracula-orange)
 | 
			
		||||
               (font-lock-comment-face :foreground ,dracula-comment)
 | 
			
		||||
               (font-lock-comment-delimiter-face :foreground ,dracula-comment)
 | 
			
		||||
               (font-lock-constant-face :foreground ,dracula-cyan)
 | 
			
		||||
               (font-lock-doc-face :foreground ,dracula-comment)
 | 
			
		||||
               (font-lock-function-name-face :foreground ,dracula-green :weight bold)
 | 
			
		||||
               (font-lock-keyword-face :weight bold :foreground ,dracula-pink)
 | 
			
		||||
               (font-lock-negation-char-face :foreground ,dracula-cyan)
 | 
			
		||||
               (font-lock-preprocessor-face :foreground ,dracula-orange)
 | 
			
		||||
               (font-lock-reference-face :foreground ,dracula-cyan)
 | 
			
		||||
               (font-lock-regexp-grouping-backslash :foreground ,dracula-cyan)
 | 
			
		||||
               (font-lock-regexp-grouping-construct :foreground ,dracula-purple)
 | 
			
		||||
               (font-lock-string-face :foreground ,dracula-yellow)
 | 
			
		||||
               (font-lock-type-face :foreground ,dracula-purple)
 | 
			
		||||
               (font-lock-variable-name-face :foreground ,dracula-fg
 | 
			
		||||
                                             :weight bold)
 | 
			
		||||
               (font-lock-warning-face :foreground ,dracula-orange :background ,bg2)
 | 
			
		||||
               ;; auto-complete
 | 
			
		||||
               (ac-completion-face :underline t :foreground ,dracula-pink)
 | 
			
		||||
               ;; company
 | 
			
		||||
               (company-echo-common :foreground ,dracula-bg :background ,dracula-fg)
 | 
			
		||||
               (company-preview :background ,dracula-current :foreground ,other-blue)
 | 
			
		||||
               (company-preview-common :inherit company-preview
 | 
			
		||||
                                       :foreground ,dracula-pink)
 | 
			
		||||
               (company-preview-search :inherit company-preview
 | 
			
		||||
                                       :foreground ,dracula-green)
 | 
			
		||||
               (company-scrollbar-bg :background ,dracula-comment)
 | 
			
		||||
               (company-scrollbar-fg :foreground ,other-blue)
 | 
			
		||||
               (company-tooltip :foreground ,dracula-fg :background ,dracula-current)
 | 
			
		||||
               (company-tooltip-search :foreground ,dracula-green
 | 
			
		||||
                                       :underline t)
 | 
			
		||||
               (company-tooltip-search-selection :background ,dracula-green
 | 
			
		||||
                                                 :foreground ,dracula-bg)
 | 
			
		||||
               (company-tooltip-selection :inherit match)
 | 
			
		||||
               (company-tooltip-mouse :background ,dracula-bg)
 | 
			
		||||
               (company-tooltip-common :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               ;;(company-tooltip-common-selection :inherit company-tooltip-common)
 | 
			
		||||
               (company-tooltip-annotation :foreground ,dracula-cyan)
 | 
			
		||||
               ;;(company-tooltip-annotation-selection :inherit company-tooltip-annotation)
 | 
			
		||||
               ;; diff-hl
 | 
			
		||||
               (diff-hl-change :foreground ,dracula-orange :background ,dracula-orange)
 | 
			
		||||
               (diff-hl-delete :foreground ,dracula-red :background ,dracula-red)
 | 
			
		||||
               (diff-hl-insert :foreground ,dracula-green :background ,dracula-green)
 | 
			
		||||
               ;; dired
 | 
			
		||||
               (dired-directory :foreground ,dracula-green :weight normal)
 | 
			
		||||
               (dired-flagged :foreground ,dracula-pink)
 | 
			
		||||
               (dired-header :foreground ,fg3 :background ,dracula-bg)
 | 
			
		||||
               (dired-ignored :inherit shadow)
 | 
			
		||||
               (dired-mark :foreground ,dracula-fg :weight bold)
 | 
			
		||||
               (dired-marked :foreground ,dracula-orange :weight bold)
 | 
			
		||||
               (dired-perm-write :foreground ,fg3 :underline t)
 | 
			
		||||
               (dired-symlink :foreground ,dracula-yellow :weight normal :slant italic)
 | 
			
		||||
               (dired-warning :foreground ,dracula-orange :underline t)
 | 
			
		||||
               (diredp-compressed-file-name :foreground ,fg3)
 | 
			
		||||
               (diredp-compressed-file-suffix :foreground ,fg4)
 | 
			
		||||
               (diredp-date-time :foreground ,dracula-fg)
 | 
			
		||||
               (diredp-deletion-file-name :foreground ,dracula-pink :background ,dracula-current)
 | 
			
		||||
               (diredp-deletion :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (diredp-dir-heading :foreground ,fg2 :background ,bg4)
 | 
			
		||||
               (diredp-dir-name :inherit dired-directory)
 | 
			
		||||
               (diredp-dir-priv :inherit dired-directory)
 | 
			
		||||
               (diredp-executable-tag :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-file-name :foreground ,dracula-fg)
 | 
			
		||||
               (diredp-file-suffix :foreground ,fg4)
 | 
			
		||||
               (diredp-flag-mark-line :foreground ,fg2 :slant italic :background ,dracula-current)
 | 
			
		||||
               (diredp-flag-mark :foreground ,fg2 :weight bold :background ,dracula-current)
 | 
			
		||||
               (diredp-ignored-file-name :foreground ,dracula-fg)
 | 
			
		||||
               (diredp-mode-line-flagged :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-mode-line-marked :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-no-priv :foreground ,dracula-fg)
 | 
			
		||||
               (diredp-number :foreground ,dracula-cyan)
 | 
			
		||||
               (diredp-other-priv :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-rare-priv :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-read-priv :foreground ,dracula-purple)
 | 
			
		||||
               (diredp-write-priv :foreground ,dracula-pink)
 | 
			
		||||
               (diredp-exec-priv :foreground ,dracula-yellow)
 | 
			
		||||
               (diredp-symlink :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-link-priv :foreground ,dracula-orange)
 | 
			
		||||
               (diredp-autofile-name :foreground ,dracula-yellow)
 | 
			
		||||
               (diredp-tagged-autofile-name :foreground ,dracula-yellow)
 | 
			
		||||
               ;; elfeed
 | 
			
		||||
               (elfeed-search-date-face :foreground ,dracula-comment)
 | 
			
		||||
               (elfeed-search-title-face :foreground ,dracula-fg)
 | 
			
		||||
               (elfeed-search-unread-title-face :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (elfeed-search-feed-face :foreground ,dracula-fg :weight bold)
 | 
			
		||||
               (elfeed-search-tag-face :foreground ,dracula-green)
 | 
			
		||||
               (elfeed-search-last-update-face :weight bold)
 | 
			
		||||
               (elfeed-search-unread-count-face :foreground ,dracula-pink)
 | 
			
		||||
               (elfeed-search-filter-face :foreground ,dracula-green :weight bold)
 | 
			
		||||
               ;;(elfeed-log-date-face :inherit font-lock-type-face)
 | 
			
		||||
               (elfeed-log-error-level-face :foreground ,dracula-red)
 | 
			
		||||
               (elfeed-log-warn-level-face :foreground ,dracula-orange)
 | 
			
		||||
               (elfeed-log-info-level-face :foreground ,dracula-cyan)
 | 
			
		||||
               (elfeed-log-debug-level-face :foreground ,dracula-comment)
 | 
			
		||||
               ;; enh-ruby
 | 
			
		||||
               (enh-ruby-heredoc-delimiter-face :foreground ,dracula-yellow)
 | 
			
		||||
               (enh-ruby-op-face :foreground ,dracula-pink)
 | 
			
		||||
               (enh-ruby-regexp-delimiter-face :foreground ,dracula-yellow)
 | 
			
		||||
               (enh-ruby-string-delimiter-face :foreground ,dracula-yellow)
 | 
			
		||||
               ;; flyspell
 | 
			
		||||
               (flyspell-duplicate :underline (:style wave :color ,dracula-orange))
 | 
			
		||||
               (flyspell-incorrect :underline (:style wave :color ,dracula-red))
 | 
			
		||||
               ;; font-latex
 | 
			
		||||
               (font-latex-bold-face :foreground ,dracula-purple)
 | 
			
		||||
               (font-latex-italic-face :foreground ,dracula-pink :slant italic)
 | 
			
		||||
               (font-latex-match-reference-keywords :foreground ,dracula-cyan)
 | 
			
		||||
               (font-latex-match-variable-keywords :foreground ,dracula-fg)
 | 
			
		||||
               (font-latex-string-face :foreground ,dracula-yellow)
 | 
			
		||||
               ;; gnus-group
 | 
			
		||||
               (gnus-group-mail-1 :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (gnus-group-mail-1-empty :inherit gnus-group-mail-1 :weight normal)
 | 
			
		||||
               (gnus-group-mail-2 :foreground ,dracula-cyan :weight bold)
 | 
			
		||||
               (gnus-group-mail-2-empty :inherit gnus-group-mail-2 :weight normal)
 | 
			
		||||
               (gnus-group-mail-3 :foreground ,dracula-comment :weight bold)
 | 
			
		||||
               (gnus-group-mail-3-empty :inherit gnus-group-mail-3 :weight normal)
 | 
			
		||||
               (gnus-group-mail-low :foreground ,dracula-current :weight bold)
 | 
			
		||||
               (gnus-group-mail-low-empty :inherit gnus-group-mail-low :weight normal)
 | 
			
		||||
               (gnus-group-news-1 :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (gnus-group-news-1-empty :inherit gnus-group-news-1 :weight normal)
 | 
			
		||||
               (gnus-group-news-2 :foreground ,dracula-cyan :weight bold)
 | 
			
		||||
               (gnus-group-news-2-empty :inherit gnus-group-news-2 :weight normal)
 | 
			
		||||
               (gnus-group-news-3 :foreground ,dracula-comment :weight bold)
 | 
			
		||||
               (gnus-group-news-3-empty :inherit gnus-group-news-3 :weight normal)
 | 
			
		||||
               (gnus-group-news-4 :inherit gnus-group-news-low)
 | 
			
		||||
               (gnus-group-news-4-empty :inherit gnus-group-news-low-empty)
 | 
			
		||||
               (gnus-group-news-5 :inherit gnus-group-news-low)
 | 
			
		||||
               (gnus-group-news-5-empty :inherit gnus-group-news-low-empty)
 | 
			
		||||
               (gnus-group-news-6 :inherit gnus-group-news-low)
 | 
			
		||||
               (gnus-group-news-6-empty :inherit gnus-group-news-low-empty)
 | 
			
		||||
               (gnus-group-news-low :foreground ,dracula-current :weight bold)
 | 
			
		||||
               (gnus-group-news-low-empty :inherit gnus-group-news-low :weight normal)
 | 
			
		||||
               (gnus-header-content :foreground ,dracula-pink)
 | 
			
		||||
               (gnus-header-from :foreground ,dracula-fg)
 | 
			
		||||
               (gnus-header-name :foreground ,dracula-purple)
 | 
			
		||||
               (gnus-header-subject :foreground ,dracula-green :weight bold)
 | 
			
		||||
               (gnus-summary-markup-face :foreground ,dracula-cyan)
 | 
			
		||||
               (gnus-summary-high-unread :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (gnus-summary-high-read :inherit gnus-summary-high-unread :weight normal)
 | 
			
		||||
               (gnus-summary-high-ancient :inherit gnus-summary-high-read)
 | 
			
		||||
               (gnus-summary-high-ticked :inherit gnus-summary-high-read :underline t)
 | 
			
		||||
               (gnus-summary-normal-unread :foreground ,other-blue :weight bold)
 | 
			
		||||
               (gnus-summary-normal-read :foreground ,dracula-comment :weight normal)
 | 
			
		||||
               (gnus-summary-normal-ancient :inherit gnus-summary-normal-read :weight light)
 | 
			
		||||
               (gnus-summary-normal-ticked :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (gnus-summary-low-unread :foreground ,dracula-comment :weight bold)
 | 
			
		||||
               (gnus-summary-low-read :inherit gnus-summary-low-unread :weight normal)
 | 
			
		||||
               (gnus-summary-low-ancient :inherit gnus-summary-low-read)
 | 
			
		||||
               (gnus-summary-low-ticked :inherit gnus-summary-low-read :underline t)
 | 
			
		||||
               (gnus-summary-selected :inverse-video t)
 | 
			
		||||
               ;; haskell-mode
 | 
			
		||||
               (haskell-operator-face :foreground ,dracula-pink)
 | 
			
		||||
               (haskell-constructor-face :foreground ,dracula-purple)
 | 
			
		||||
               ;; helm
 | 
			
		||||
               (helm-bookmark-w3m :foreground ,dracula-purple)
 | 
			
		||||
               (helm-buffer-not-saved :foreground ,dracula-purple :background ,dracula-bg)
 | 
			
		||||
               (helm-buffer-process :foreground ,dracula-orange :background ,dracula-bg)
 | 
			
		||||
               (helm-buffer-saved-out :foreground ,dracula-fg :background ,dracula-bg)
 | 
			
		||||
               (helm-buffer-size :foreground ,dracula-fg :background ,dracula-bg)
 | 
			
		||||
               (helm-candidate-number :foreground ,dracula-bg :background ,dracula-fg)
 | 
			
		||||
               (helm-ff-directory :foreground ,dracula-green :background ,dracula-bg :weight bold)
 | 
			
		||||
               (helm-ff-dotted-directory :foreground ,dracula-green :background ,dracula-bg :weight normal)
 | 
			
		||||
               (helm-ff-executable :foreground ,other-blue :background ,dracula-bg :weight normal)
 | 
			
		||||
               (helm-ff-file :foreground ,dracula-fg :background ,dracula-bg :weight normal)
 | 
			
		||||
               (helm-ff-invalid-symlink :foreground ,dracula-pink :background ,dracula-bg :weight bold)
 | 
			
		||||
               (helm-ff-prefix :foreground ,dracula-bg :background ,dracula-pink :weight normal)
 | 
			
		||||
               (helm-ff-symlink :foreground ,dracula-pink :background ,dracula-bg :weight bold)
 | 
			
		||||
               (helm-grep-cmd-line :foreground ,dracula-fg :background ,dracula-bg)
 | 
			
		||||
               (helm-grep-file :foreground ,dracula-fg :background ,dracula-bg)
 | 
			
		||||
               (helm-grep-finish :foreground ,fg2 :background ,dracula-bg)
 | 
			
		||||
               (helm-grep-lineno :foreground ,dracula-fg :background ,dracula-bg)
 | 
			
		||||
               (helm-grep-match :foreground "unspecified-fg" :background "unspecified-bg" :inherit helm-match)
 | 
			
		||||
               (helm-grep-running :foreground ,dracula-green :background ,dracula-bg)
 | 
			
		||||
               (helm-header :foreground ,fg2 :background ,dracula-bg :underline nil :box nil)
 | 
			
		||||
               (helm-moccur-buffer :foreground ,dracula-green :background ,dracula-bg)
 | 
			
		||||
               (helm-selection :background ,bg2 :underline nil)
 | 
			
		||||
               (helm-selection-line :background ,bg2)
 | 
			
		||||
               (helm-separator :foreground ,dracula-purple :background ,dracula-bg)
 | 
			
		||||
               (helm-source-go-package-godoc-description :foreground ,dracula-yellow)
 | 
			
		||||
               (helm-source-header :foreground ,dracula-pink :background ,dracula-bg :underline nil :weight bold)
 | 
			
		||||
               (helm-time-zone-current :foreground ,dracula-orange :background ,dracula-bg)
 | 
			
		||||
               (helm-time-zone-home :foreground ,dracula-purple :background ,dracula-bg)
 | 
			
		||||
               (helm-visible-mark :foreground ,dracula-bg :background ,bg3)
 | 
			
		||||
               ;; highlight-indentation minor mode
 | 
			
		||||
               (highlight-indentation-face :background ,bg2)
 | 
			
		||||
               ;; icicle
 | 
			
		||||
               (icicle-whitespace-highlight :background ,dracula-fg)
 | 
			
		||||
               (icicle-special-candidate :foreground ,fg2)
 | 
			
		||||
               (icicle-extra-candidate :foreground ,fg2)
 | 
			
		||||
               (icicle-search-main-regexp-others :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-search-current-input :foreground ,dracula-pink)
 | 
			
		||||
               (icicle-search-context-level-8 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-7 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-6 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-5 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-4 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-3 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-2 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-context-level-1 :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-search-main-regexp-current :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-saved-candidate :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-proxy-candidate :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-mustmatch-completion :foreground ,dracula-purple)
 | 
			
		||||
               (icicle-multi-command-completion :foreground ,fg2 :background ,bg2)
 | 
			
		||||
               (icicle-msg-emphasis :foreground ,dracula-green)
 | 
			
		||||
               (icicle-mode-line-help :foreground ,fg4)
 | 
			
		||||
               (icicle-match-highlight-minibuffer :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-match-highlight-Completions :foreground ,dracula-green)
 | 
			
		||||
               (icicle-key-complete-menu-local :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-key-complete-menu :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-input-completion-fail-lax :foreground ,dracula-pink)
 | 
			
		||||
               (icicle-input-completion-fail :foreground ,dracula-pink)
 | 
			
		||||
               (icicle-historical-candidate-other :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-historical-candidate :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-current-candidate-highlight :foreground ,dracula-orange :background ,bg3)
 | 
			
		||||
               (icicle-Completions-instruction-2 :foreground ,fg4)
 | 
			
		||||
               (icicle-Completions-instruction-1 :foreground ,fg4)
 | 
			
		||||
               (icicle-completion :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-complete-input :foreground ,dracula-orange)
 | 
			
		||||
               (icicle-common-match-highlight-Completions :foreground ,dracula-purple)
 | 
			
		||||
               (icicle-candidate-part :foreground ,dracula-fg)
 | 
			
		||||
               (icicle-annotation :foreground ,fg4)
 | 
			
		||||
               ;; icomplete
 | 
			
		||||
               (icompletep-determined :foreground ,dracula-orange)
 | 
			
		||||
               ;; ido
 | 
			
		||||
               (ido-first-match
 | 
			
		||||
                ,@(if dracula-alternate-mode-line-and-minibuffer
 | 
			
		||||
                      (list :weight 'normal :foreground dracula-green)
 | 
			
		||||
                    (list :weight 'bold :foreground dracula-pink)))
 | 
			
		||||
               (ido-only-match :foreground ,dracula-orange)
 | 
			
		||||
               (ido-subdir :foreground ,dracula-yellow)
 | 
			
		||||
               (ido-virtual :foreground ,dracula-cyan)
 | 
			
		||||
               (ido-incomplete-regexp :inherit font-lock-warning-face)
 | 
			
		||||
               (ido-indicator :foreground ,dracula-fg :background ,dracula-pink)
 | 
			
		||||
               ;; isearch
 | 
			
		||||
               (isearch :inherit match :weight bold)
 | 
			
		||||
               (isearch-fail :foreground ,dracula-bg :background ,dracula-orange)
 | 
			
		||||
               ;; jde-java
 | 
			
		||||
               (jde-java-font-lock-constant-face :foreground ,dracula-cyan)
 | 
			
		||||
               (jde-java-font-lock-modifier-face :foreground ,dracula-pink)
 | 
			
		||||
               (jde-java-font-lock-number-face :foreground ,dracula-fg)
 | 
			
		||||
               (jde-java-font-lock-package-face :foreground ,dracula-fg)
 | 
			
		||||
               (jde-java-font-lock-private-face :foreground ,dracula-pink)
 | 
			
		||||
               (jde-java-font-lock-public-face :foreground ,dracula-pink)
 | 
			
		||||
               ;; js2-mode
 | 
			
		||||
               (js2-external-variable :foreground ,dracula-purple)
 | 
			
		||||
               (js2-function-param :foreground ,dracula-cyan)
 | 
			
		||||
               (js2-jsdoc-html-tag-delimiter :foreground ,dracula-yellow)
 | 
			
		||||
               (js2-jsdoc-html-tag-name :foreground ,other-blue)
 | 
			
		||||
               (js2-jsdoc-value :foreground ,dracula-yellow)
 | 
			
		||||
               (js2-private-function-call :foreground ,dracula-cyan)
 | 
			
		||||
               (js2-private-member :foreground ,fg3)
 | 
			
		||||
               ;; js3-mode
 | 
			
		||||
               (js3-error-face :underline ,dracula-orange)
 | 
			
		||||
               (js3-external-variable-face :foreground ,dracula-fg)
 | 
			
		||||
               (js3-function-param-face :foreground ,dracula-pink)
 | 
			
		||||
               (js3-instance-member-face :foreground ,dracula-cyan)
 | 
			
		||||
               (js3-jsdoc-tag-face :foreground ,dracula-pink)
 | 
			
		||||
               (js3-warning-face :underline ,dracula-pink)
 | 
			
		||||
               ;; lsp
 | 
			
		||||
               (lsp-ui-peek-peek :background ,dracula-bg)
 | 
			
		||||
               (lsp-ui-peek-list :background ,bg2)
 | 
			
		||||
               (lsp-ui-peek-filename :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (lsp-ui-peek-line-number :foreground ,dracula-fg)
 | 
			
		||||
               (lsp-ui-peek-highlight :inherit highlight :distant-foreground ,dracula-bg)
 | 
			
		||||
               (lsp-ui-peek-header :background ,bg3 :foreground ,fg3, :weight bold)
 | 
			
		||||
               (lsp-ui-peek-footer :inherit lsp-ui-peek-header)
 | 
			
		||||
               (lsp-ui-peek-selection :inherit match)
 | 
			
		||||
               (lsp-ui-sideline-symbol :foreground ,fg4 :box (:line-width -1 :color ,fg4) :height 0.99)
 | 
			
		||||
               (lsp-ui-sideline-current-symbol :foreground ,dracula-fg :weight ultra-bold
 | 
			
		||||
                                               :box (:line-width -1 :color dracula-fg) :height 0.99)
 | 
			
		||||
               (lsp-ui-sideline-code-action :foreground ,dracula-yellow)
 | 
			
		||||
               (lsp-ui-sideline-symbol-info :slant italic :height 0.99)
 | 
			
		||||
               (lsp-ui-doc-background :background ,dracula-bg)
 | 
			
		||||
               (lsp-ui-doc-header :foreground ,dracula-bg :background ,dracula-cyan)
 | 
			
		||||
               ;; magit
 | 
			
		||||
               (magit-branch-local :foreground ,dracula-cyan)
 | 
			
		||||
               (magit-branch-remote :foreground ,dracula-green)
 | 
			
		||||
               (magit-tag :foreground ,dracula-orange)
 | 
			
		||||
               (magit-section-heading :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (magit-section-highlight :background ,bg3 :extend t)
 | 
			
		||||
               (magit-diff-context-highlight :background ,bg3
 | 
			
		||||
                                             :foreground ,fg3
 | 
			
		||||
                                             :extend t)
 | 
			
		||||
               (magit-diff-revision-summary :foreground ,dracula-orange
 | 
			
		||||
                                            :background ,dracula-bg
 | 
			
		||||
                                            :weight bold)
 | 
			
		||||
               (magit-diff-revision-summary-highlight :foreground ,dracula-orange
 | 
			
		||||
                                                      :background ,bg3
 | 
			
		||||
                                                      :weight bold
 | 
			
		||||
                                                      :extend t)
 | 
			
		||||
               ;; the four following lines are just a patch of the
 | 
			
		||||
               ;; upstream color to add the extend keyword.
 | 
			
		||||
               (magit-diff-added :background "#335533"
 | 
			
		||||
                                 :foreground "#ddffdd"
 | 
			
		||||
                                 :extend t)
 | 
			
		||||
               (magit-diff-added-highlight :background "#336633"
 | 
			
		||||
                                           :foreground "#cceecc"
 | 
			
		||||
                                           :extend t)
 | 
			
		||||
               (magit-diff-removed :background "#553333"
 | 
			
		||||
                                   :foreground "#ffdddd"
 | 
			
		||||
                                   :extend t)
 | 
			
		||||
               (magit-diff-removed-highlight :background "#663333"
 | 
			
		||||
                                             :foreground "#eecccc"
 | 
			
		||||
                                             :extend t)
 | 
			
		||||
               (magit-diff-file-heading :foreground ,dracula-fg)
 | 
			
		||||
               (magit-diff-file-heading-highlight :inherit magit-section-highlight)
 | 
			
		||||
               (magit-diffstat-added :foreground ,dracula-green)
 | 
			
		||||
               (magit-diffstat-removed :foreground ,dracula-red)
 | 
			
		||||
               (magit-hash :foreground ,fg2)
 | 
			
		||||
               (magit-hunk-heading :background ,bg3)
 | 
			
		||||
               (magit-hunk-heading-highlight :background ,bg3)
 | 
			
		||||
               (magit-item-highlight :background ,bg3)
 | 
			
		||||
               (magit-log-author :foreground ,fg3)
 | 
			
		||||
               (magit-process-ng :foreground ,dracula-orange :weight bold)
 | 
			
		||||
               (magit-process-ok :foreground ,dracula-green :weight bold)
 | 
			
		||||
               ;; markdown
 | 
			
		||||
               (markdown-blockquote-face :foreground ,dracula-orange)
 | 
			
		||||
               (markdown-code-face :foreground ,dracula-orange)
 | 
			
		||||
               (markdown-footnote-face :foreground ,other-blue)
 | 
			
		||||
               (markdown-header-face :weight normal)
 | 
			
		||||
               (markdown-header-face-1
 | 
			
		||||
                :inherit bold :foreground ,dracula-pink
 | 
			
		||||
                ,@(when dracula-enlarge-headings
 | 
			
		||||
                    (list :height dracula-height-title-1)))
 | 
			
		||||
               (markdown-header-face-2
 | 
			
		||||
                :inherit bold :foreground ,dracula-purple
 | 
			
		||||
                ,@(when dracula-enlarge-headings
 | 
			
		||||
                    (list :height dracula-height-title-2)))
 | 
			
		||||
               (markdown-header-face-3
 | 
			
		||||
                :foreground ,dracula-green
 | 
			
		||||
                ,@(when dracula-enlarge-headings
 | 
			
		||||
                    (list :height dracula-height-title-3)))
 | 
			
		||||
               (markdown-header-face-4 :foreground ,dracula-yellow)
 | 
			
		||||
               (markdown-header-face-5 :foreground ,dracula-cyan)
 | 
			
		||||
               (markdown-header-face-6 :foreground ,dracula-orange)
 | 
			
		||||
               (markdown-header-face-7 :foreground ,other-blue)
 | 
			
		||||
               (markdown-header-face-8 :foreground ,dracula-fg)
 | 
			
		||||
               (markdown-inline-code-face :foreground ,dracula-yellow)
 | 
			
		||||
               (markdown-plain-url-face :inherit link)
 | 
			
		||||
               (markdown-pre-face :foreground ,dracula-orange)
 | 
			
		||||
               (markdown-table-face :foreground ,dracula-purple)
 | 
			
		||||
               ;; message
 | 
			
		||||
               (message-header-to :foreground ,dracula-fg :weight bold)
 | 
			
		||||
               (message-header-cc :foreground ,dracula-fg :bold bold)
 | 
			
		||||
               (message-header-subject :foreground ,dracula-orange)
 | 
			
		||||
               (message-header-newsgroups :foreground ,dracula-purple)
 | 
			
		||||
               (message-header-other :foreground ,dracula-purple)
 | 
			
		||||
               (message-header-name :foreground ,dracula-green)
 | 
			
		||||
               (message-header-xheader :foreground ,dracula-cyan)
 | 
			
		||||
               (message-separator :foreground ,dracula-cyan :slant italic)
 | 
			
		||||
               (message-cited-text :foreground ,dracula-purple)
 | 
			
		||||
               (message-cited-text-1 :foreground ,dracula-purple)
 | 
			
		||||
               (message-cited-text-2 :foreground ,dracula-orange)
 | 
			
		||||
               (message-cited-text-3 :foreground ,dracula-comment)
 | 
			
		||||
               (message-cited-text-4 :foreground ,fg2)
 | 
			
		||||
               (message-mml :foreground ,dracula-green :weight normal)
 | 
			
		||||
               ;; mode-line
 | 
			
		||||
               (mode-line :background ,dracula-current
 | 
			
		||||
                          :box ,dracula-current :inverse-video nil
 | 
			
		||||
                          ,@(if dracula-alternate-mode-line-and-minibuffer
 | 
			
		||||
                                (list :foreground fg3)
 | 
			
		||||
                              (list :foreground "unspecified-fg")))
 | 
			
		||||
               (mode-line-inactive
 | 
			
		||||
                :inverse-video nil
 | 
			
		||||
                ,@(if dracula-alternate-mode-line-and-minibuffer
 | 
			
		||||
                      (list :foreground dracula-comment :background dracula-bg
 | 
			
		||||
                            :box dracula-bg)
 | 
			
		||||
                    (list :foreground dracula-fg :background bg2 :box bg2)))
 | 
			
		||||
               ;; mu4e
 | 
			
		||||
               (mu4e-unread-face :foreground ,dracula-pink :weight normal)
 | 
			
		||||
               (mu4e-view-url-number-face :foreground ,dracula-purple)
 | 
			
		||||
               (mu4e-highlight-face :background ,dracula-bg
 | 
			
		||||
                                    :foreground ,dracula-yellow
 | 
			
		||||
                                    :extend t)
 | 
			
		||||
               (mu4e-header-highlight-face :background ,dracula-current
 | 
			
		||||
                                           :foreground ,dracula-fg
 | 
			
		||||
                                           :underline nil :weight bold
 | 
			
		||||
                                           :extend t)
 | 
			
		||||
               (mu4e-header-key-face :inherit message-mml)
 | 
			
		||||
               (mu4e-header-marks-face :foreground ,dracula-purple)
 | 
			
		||||
               (mu4e-cited-1-face :foreground ,dracula-purple)
 | 
			
		||||
               (mu4e-cited-2-face :foreground ,dracula-orange)
 | 
			
		||||
               (mu4e-cited-3-face :foreground ,dracula-comment)
 | 
			
		||||
               (mu4e-cited-4-face :foreground ,fg2)
 | 
			
		||||
               (mu4e-cited-5-face :foreground ,fg3)
 | 
			
		||||
               ;; neotree
 | 
			
		||||
               (neo-banner-face :foreground ,dracula-orange :weight bold)
 | 
			
		||||
               ;;(neo-button-face :underline nil)
 | 
			
		||||
               (neo-dir-link-face :foreground ,dracula-purple)
 | 
			
		||||
               (neo-expand-btn-face :foreground ,dracula-fg)
 | 
			
		||||
               (neo-file-link-face :foreground ,dracula-cyan)
 | 
			
		||||
               (neo-header-face :background ,dracula-bg
 | 
			
		||||
                                :foreground ,dracula-fg
 | 
			
		||||
                                :weight bold)
 | 
			
		||||
               (neo-root-dir-face :foreground ,dracula-purple :weight bold)
 | 
			
		||||
               (neo-vc-added-face :foreground ,dracula-orange)
 | 
			
		||||
               (neo-vc-conflict-face :foreground ,dracula-red)
 | 
			
		||||
               (neo-vc-default-face :inherit neo-file-link-face)
 | 
			
		||||
               (neo-vc-edited-face :foreground ,dracula-orange)
 | 
			
		||||
               (neo-vc-ignored-face :foreground ,dracula-comment)
 | 
			
		||||
               (neo-vc-missing-face :foreground ,dracula-red)
 | 
			
		||||
               (neo-vc-needs-merge-face :foreground ,dracula-red
 | 
			
		||||
                                        :weight bold)
 | 
			
		||||
               ;;(neo-vc-needs-update-face :underline t)
 | 
			
		||||
               ;;(neo-vc-removed-face :strike-through t)
 | 
			
		||||
               (neo-vc-unlocked-changes-face :foreground ,dracula-red)
 | 
			
		||||
               ;;(neo-vc-unregistered-face nil)
 | 
			
		||||
               (neo-vc-up-to-date-face :foreground ,dracula-green)
 | 
			
		||||
               (neo-vc-user-face :foreground ,dracula-purple)
 | 
			
		||||
               ;; org
 | 
			
		||||
               (org-agenda-date :foreground ,dracula-cyan :underline nil)
 | 
			
		||||
               (org-agenda-dimmed-todo-face :foreground ,dracula-comment)
 | 
			
		||||
               (org-agenda-done :foreground ,dracula-green)
 | 
			
		||||
               (org-agenda-structure :foreground ,dracula-purple)
 | 
			
		||||
               (org-block :foreground ,dracula-orange)
 | 
			
		||||
               (org-code :foreground ,dracula-yellow)
 | 
			
		||||
               (org-column :background ,bg4)
 | 
			
		||||
               (org-column-title :inherit org-column :weight bold :underline t)
 | 
			
		||||
               (org-date :foreground ,dracula-cyan :underline t)
 | 
			
		||||
               (org-document-info :foreground ,other-blue)
 | 
			
		||||
               (org-document-info-keyword :foreground ,dracula-comment)
 | 
			
		||||
               (org-document-title :weight bold :foreground ,dracula-orange
 | 
			
		||||
                                   ,@(when dracula-enlarge-headings
 | 
			
		||||
                                       (list :height dracula-height-doc-title)))
 | 
			
		||||
               (org-done :foreground ,dracula-green)
 | 
			
		||||
               (org-ellipsis :foreground ,dracula-comment)
 | 
			
		||||
               (org-footnote :foreground ,other-blue)
 | 
			
		||||
               (org-formula :foreground ,dracula-pink)
 | 
			
		||||
               (org-headline-done :foreground ,dracula-comment
 | 
			
		||||
                                  :weight normal :strike-through t)
 | 
			
		||||
               (org-hide :foreground ,dracula-bg :background ,dracula-bg)
 | 
			
		||||
               (org-level-1 :inherit bold :foreground ,dracula-pink
 | 
			
		||||
                            ,@(when dracula-enlarge-headings
 | 
			
		||||
                                (list :height dracula-height-title-1)))
 | 
			
		||||
               (org-level-2 :inherit bold :foreground ,dracula-purple
 | 
			
		||||
                            ,@(when dracula-enlarge-headings
 | 
			
		||||
                                (list :height dracula-height-title-2)))
 | 
			
		||||
               (org-level-3 :weight normal :foreground ,dracula-green
 | 
			
		||||
                            ,@(when dracula-enlarge-headings
 | 
			
		||||
                                (list :height dracula-height-title-3)))
 | 
			
		||||
               (org-level-4 :weight normal :foreground ,dracula-yellow)
 | 
			
		||||
               (org-level-5 :weight normal :foreground ,dracula-cyan)
 | 
			
		||||
               (org-level-6 :weight normal :foreground ,dracula-orange)
 | 
			
		||||
               (org-level-7 :weight normal :foreground ,other-blue)
 | 
			
		||||
               (org-level-8 :weight normal :foreground ,dracula-fg)
 | 
			
		||||
               (org-link :foreground ,dracula-cyan :underline t)
 | 
			
		||||
               (org-priority :foreground ,dracula-cyan)
 | 
			
		||||
               (org-scheduled :foreground ,dracula-green)
 | 
			
		||||
               (org-scheduled-previously :foreground ,dracula-yellow)
 | 
			
		||||
               (org-scheduled-today :foreground ,dracula-green)
 | 
			
		||||
               (org-sexp-date :foreground ,fg4)
 | 
			
		||||
               (org-special-keyword :foreground ,dracula-yellow)
 | 
			
		||||
               (org-table :foreground ,dracula-purple)
 | 
			
		||||
               (org-tag :foreground ,dracula-pink :weight bold :background ,bg2)
 | 
			
		||||
               (org-todo :foreground ,dracula-orange :weight bold :background ,bg2)
 | 
			
		||||
               (org-upcoming-deadline :foreground ,dracula-yellow)
 | 
			
		||||
               (org-warning :weight bold :foreground ,dracula-pink)
 | 
			
		||||
               ;; outline
 | 
			
		||||
               (outline-1 :foreground ,dracula-pink)
 | 
			
		||||
               (outline-2 :foreground ,dracula-purple)
 | 
			
		||||
               (outline-3 :foreground ,dracula-green)
 | 
			
		||||
               (outline-4 :foreground ,dracula-yellow)
 | 
			
		||||
               (outline-5 :foreground ,dracula-cyan)
 | 
			
		||||
               (outline-6 :foreground ,dracula-orange)
 | 
			
		||||
               ;; powerline
 | 
			
		||||
               (powerline-evil-base-face :foreground ,bg2)
 | 
			
		||||
               (powerline-evil-emacs-face :inherit powerline-evil-base-face :background ,dracula-yellow)
 | 
			
		||||
               (powerline-evil-insert-face :inherit powerline-evil-base-face :background ,dracula-cyan)
 | 
			
		||||
               (powerline-evil-motion-face :inherit powerline-evil-base-face :background ,dracula-purple)
 | 
			
		||||
               (powerline-evil-normal-face :inherit powerline-evil-base-face :background ,dracula-green)
 | 
			
		||||
               (powerline-evil-operator-face :inherit powerline-evil-base-face :background ,dracula-pink)
 | 
			
		||||
               (powerline-evil-replace-face :inherit powerline-evil-base-face :background ,dracula-red)
 | 
			
		||||
               (powerline-evil-visual-face :inherit powerline-evil-base-face :background ,dracula-orange)
 | 
			
		||||
               ;; rainbow-delimiters
 | 
			
		||||
               (rainbow-delimiters-depth-1-face :foreground ,dracula-fg)
 | 
			
		||||
               (rainbow-delimiters-depth-2-face :foreground ,dracula-cyan)
 | 
			
		||||
               (rainbow-delimiters-depth-3-face :foreground ,dracula-purple)
 | 
			
		||||
               (rainbow-delimiters-depth-4-face :foreground ,dracula-pink)
 | 
			
		||||
               (rainbow-delimiters-depth-5-face :foreground ,dracula-orange)
 | 
			
		||||
               (rainbow-delimiters-depth-6-face :foreground ,dracula-green)
 | 
			
		||||
               (rainbow-delimiters-depth-7-face :foreground ,dracula-yellow)
 | 
			
		||||
               (rainbow-delimiters-depth-8-face :foreground ,other-blue)
 | 
			
		||||
               (rainbow-delimiters-unmatched-face :foreground ,dracula-orange)
 | 
			
		||||
               ;; rpm-spec
 | 
			
		||||
               (rpm-spec-dir-face :foreground ,dracula-green)
 | 
			
		||||
               (rpm-spec-doc-face :foreground ,dracula-pink)
 | 
			
		||||
               (rpm-spec-ghost-face :foreground ,dracula-purple)
 | 
			
		||||
               (rpm-spec-macro-face :foreground ,dracula-yellow)
 | 
			
		||||
               (rpm-spec-obsolete-tag-face :inherit font-lock-warning-face)
 | 
			
		||||
               (rpm-spec-package-face :foreground ,dracula-purple)
 | 
			
		||||
               (rpm-spec-section-face :foreground ,dracula-yellow)
 | 
			
		||||
               (rpm-spec-tag-face :foreground ,dracula-cyan)
 | 
			
		||||
               (rpm-spec-var-face :foreground ,dracula-orange)
 | 
			
		||||
               ;; show-paren
 | 
			
		||||
               (show-paren-match-face :background unspecified
 | 
			
		||||
                                      :foreground ,dracula-cyan
 | 
			
		||||
                                      :weight bold)
 | 
			
		||||
               (show-paren-match :background unspecified
 | 
			
		||||
                                 :foreground ,dracula-cyan
 | 
			
		||||
                                 :weight bold)
 | 
			
		||||
               (show-paren-match-expression :inherit match)
 | 
			
		||||
               (show-paren-mismatch :inherit font-lock-warning-face)
 | 
			
		||||
               ;; slime
 | 
			
		||||
               (slime-repl-inputed-output-face :foreground ,dracula-purple)
 | 
			
		||||
               ;; spam
 | 
			
		||||
               (spam :inherit gnus-summary-normal-read :foreground ,dracula-orange
 | 
			
		||||
                     :strike-through t :slant oblique)
 | 
			
		||||
               ;; speedbar (and sr-speedbar)
 | 
			
		||||
               (speedbar-button-face :foreground ,dracula-green)
 | 
			
		||||
               (speedbar-file-face :foreground ,dracula-cyan)
 | 
			
		||||
               (speedbar-directory-face :foreground ,dracula-purple)
 | 
			
		||||
               (speedbar-tag-face :foreground ,dracula-yellow)
 | 
			
		||||
               (speedbar-selected-face :foreground ,dracula-pink)
 | 
			
		||||
               (speedbar-highlight-face :inherit match)
 | 
			
		||||
               (speedbar-separator-face :background ,dracula-bg
 | 
			
		||||
                                        :foreground ,dracula-fg
 | 
			
		||||
                                        :weight bold)
 | 
			
		||||
               ;; tab-bar & tab-line (since Emacs 27.1)
 | 
			
		||||
               (tab-bar :foreground ,dracula-purple :background ,dracula-current
 | 
			
		||||
                        :inherit variable-pitch)
 | 
			
		||||
               (tab-bar-tab :foreground ,dracula-pink :background ,dracula-bg
 | 
			
		||||
                            :box (:line-width 2 :color ,dracula-bg :style nil))
 | 
			
		||||
               (tab-bar-tab-inactive :foreground ,dracula-purple :background ,bg2
 | 
			
		||||
                                     :box (:line-width 2 :color ,bg2 :style nil))
 | 
			
		||||
               (tab-line :foreground ,dracula-purple :background ,dracula-current
 | 
			
		||||
                         :height 0.9 :inherit variable-pitch)
 | 
			
		||||
               (tab-line-tab :foreground ,dracula-pink :background ,dracula-bg
 | 
			
		||||
                             :box (:line-width 2 :color ,dracula-bg :style nil))
 | 
			
		||||
               (tab-line-tab-inactive :foreground ,dracula-purple :background ,bg2
 | 
			
		||||
                                      :box (:line-width 2 :color ,bg2 :style nil))
 | 
			
		||||
               (tab-line-tab-current :inherit tab-line-tab)
 | 
			
		||||
               (tab-line-close-highlight :foreground ,dracula-red)
 | 
			
		||||
               ;; term
 | 
			
		||||
               (term :foreground ,dracula-fg :background ,dracula-bg)
 | 
			
		||||
               (term-color-black :foreground ,dracula-bg :background ,dracula-bg)
 | 
			
		||||
               (term-color-blue :foreground ,dracula-purple :background ,dracula-purple)
 | 
			
		||||
               (term-color-cyan :foreground ,dracula-cyan :background ,dracula-cyan)
 | 
			
		||||
               (term-color-green :foreground ,dracula-green :background ,dracula-green)
 | 
			
		||||
               (term-color-magenta :foreground ,dracula-pink :background ,dracula-pink)
 | 
			
		||||
               (term-color-red :foreground ,dracula-red :background ,dracula-red)
 | 
			
		||||
               (term-color-white :foreground ,dracula-fg :background ,dracula-fg)
 | 
			
		||||
               (term-color-yellow :foreground ,dracula-yellow :background ,dracula-yellow)
 | 
			
		||||
               ;; undo-tree
 | 
			
		||||
               (undo-tree-visualizer-current-face :foreground ,dracula-orange)
 | 
			
		||||
               (undo-tree-visualizer-default-face :foreground ,fg2)
 | 
			
		||||
               (undo-tree-visualizer-register-face :foreground ,dracula-purple)
 | 
			
		||||
               (undo-tree-visualizer-unmodified-face :foreground ,dracula-fg)
 | 
			
		||||
               ;; web-mode
 | 
			
		||||
               (web-mode-builtin-face :inherit ,font-lock-builtin-face)
 | 
			
		||||
               (web-mode-comment-face :inherit ,font-lock-comment-face)
 | 
			
		||||
               (web-mode-constant-face :inherit ,font-lock-constant-face)
 | 
			
		||||
               (web-mode-doctype-face :inherit ,font-lock-comment-face)
 | 
			
		||||
               (web-mode-function-name-face :inherit ,font-lock-function-name-face)
 | 
			
		||||
               (web-mode-html-attr-name-face :foreground ,dracula-purple)
 | 
			
		||||
               (web-mode-html-attr-value-face :foreground ,dracula-green)
 | 
			
		||||
               (web-mode-html-tag-face :foreground ,dracula-pink :weight bold)
 | 
			
		||||
               (web-mode-keyword-face :foreground ,dracula-pink)
 | 
			
		||||
               (web-mode-string-face :foreground ,dracula-yellow)
 | 
			
		||||
               (web-mode-type-face :inherit ,font-lock-type-face)
 | 
			
		||||
               (web-mode-warning-face :inherit ,font-lock-warning-face)
 | 
			
		||||
               ;; which-func
 | 
			
		||||
               (which-func :inherit ,font-lock-function-name-face)
 | 
			
		||||
               ;; whitespace
 | 
			
		||||
               (whitespace-big-indent :background ,dracula-red :foreground ,dracula-red)
 | 
			
		||||
               (whitespace-empty :background ,dracula-orange :foreground ,dracula-red)
 | 
			
		||||
               (whitespace-hspace :background ,bg3 :foreground ,dracula-comment)
 | 
			
		||||
               (whitespace-indentation :background ,dracula-orange :foreground ,dracula-red)
 | 
			
		||||
               (whitespace-line :background ,dracula-bg :foreground ,dracula-pink)
 | 
			
		||||
               (whitespace-newline :foreground ,dracula-comment)
 | 
			
		||||
               (whitespace-space :background ,dracula-bg :foreground ,dracula-comment)
 | 
			
		||||
               (whitespace-space-after-tab :background ,dracula-orange :foreground ,dracula-red)
 | 
			
		||||
               (whitespace-space-before-tab :background ,dracula-orange :foreground ,dracula-red)
 | 
			
		||||
               (whitespace-tab :background ,bg2 :foreground ,dracula-comment)
 | 
			
		||||
               (whitespace-trailing :inherit trailing-whitespace)
 | 
			
		||||
               ;; yard-mode
 | 
			
		||||
               (yard-tag-face :inherit ,font-lock-builtin-face)
 | 
			
		||||
               (yard-directive-face :inherit ,font-lock-builtin-face))))
 | 
			
		||||
 | 
			
		||||
  (apply #'custom-theme-set-faces
 | 
			
		||||
         'dracula
 | 
			
		||||
         (let ((color-names (mapcar #'car colors))
 | 
			
		||||
               (graphic-colors (mapcar #'cadr colors))
 | 
			
		||||
               (term-colors (mapcar #'car (mapcar #'cddr colors)))
 | 
			
		||||
               (tty-colors (mapcar #'car (mapcar #'last colors)))
 | 
			
		||||
               (expand-for-kind
 | 
			
		||||
                (lambda (kind spec)
 | 
			
		||||
                  (when (and (string= (symbol-name kind) "term-colors")
 | 
			
		||||
                             dracula-use-24-bit-colors-on-256-colors-terms)
 | 
			
		||||
                    (setq kind 'graphic-colors))
 | 
			
		||||
                  (cl-progv color-names (symbol-value kind)
 | 
			
		||||
                    (eval `(backquote ,spec))))))
 | 
			
		||||
           (cl-loop for (face . spec) in faces
 | 
			
		||||
                    collect `(,face
 | 
			
		||||
                              ((((min-colors 16777216)) ; fully graphical envs
 | 
			
		||||
                                ,(funcall expand-for-kind 'graphic-colors spec))
 | 
			
		||||
                               (((min-colors 256))      ; terminal withs 256 colors
 | 
			
		||||
                                ,(funcall expand-for-kind 'term-colors spec))
 | 
			
		||||
                               (t                       ; should be only tty-like envs
 | 
			
		||||
                                ,(funcall expand-for-kind 'tty-colors spec))))))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(when load-file-name
 | 
			
		||||
  (add-to-list 'custom-theme-load-path
 | 
			
		||||
               (file-name-as-directory (file-name-directory load-file-name))))
 | 
			
		||||
 | 
			
		||||
(provide-theme 'dracula)
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; indent-tabs-mode: nil
 | 
			
		||||
;; End:
 | 
			
		||||
 | 
			
		||||
;;; dracula-theme.el ends here
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
(advice-add #'x-apply-session-resources :override #'ignore)
 | 
			
		||||
(setq make-backup-files nil
 | 
			
		||||
      auto-save-default nil
 | 
			
		||||
      visible-bell t)
 | 
			
		||||
 | 
			
		||||
(load-file "dracula-theme.el")
 | 
			
		||||
(load-theme 'dracula t)
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,53 +0,0 @@
 | 
			
		||||
;;; git-commit-autoloads.el --- automatically extracted autoloads
 | 
			
		||||
;;
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(add-to-list 'load-path (directory-file-name
 | 
			
		||||
                         (or (file-name-directory #$) (car load-path))))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
;;;### (autoloads nil "git-commit" "git-commit.el" (0 0 0 0))
 | 
			
		||||
;;; Generated autoloads from git-commit.el
 | 
			
		||||
 | 
			
		||||
(defvar global-git-commit-mode t "\
 | 
			
		||||
Non-nil if Global Git-Commit mode is enabled.
 | 
			
		||||
See the `global-git-commit-mode' command
 | 
			
		||||
for a description of this minor mode.
 | 
			
		||||
Setting this variable directly does not take effect;
 | 
			
		||||
either customize it (see the info node `Easy Customization')
 | 
			
		||||
or call the function `global-git-commit-mode'.")
 | 
			
		||||
 | 
			
		||||
(custom-autoload 'global-git-commit-mode "git-commit" nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'global-git-commit-mode "git-commit" "\
 | 
			
		||||
Edit Git commit messages.
 | 
			
		||||
This global mode arranges for `git-commit-setup' to be called
 | 
			
		||||
when a Git commit message file is opened.  That usually happens
 | 
			
		||||
when Git uses the Emacsclient as $GIT_EDITOR to have the user
 | 
			
		||||
provide such a commit message.
 | 
			
		||||
 | 
			
		||||
\(fn &optional ARG)" t nil)
 | 
			
		||||
 | 
			
		||||
(defconst git-commit-filename-regexp "/\\(\\(\\(COMMIT\\|NOTES\\|PULLREQ\\|MERGEREQ\\|TAG\\)_EDIT\\|MERGE_\\|\\)MSG\\|\\(BRANCH\\|EDIT\\)_DESCRIPTION\\)\\'")
 | 
			
		||||
 | 
			
		||||
(autoload 'git-commit-setup-check-buffer "git-commit" "\
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
\(fn)" nil nil)
 | 
			
		||||
 | 
			
		||||
(autoload 'git-commit-setup "git-commit" "\
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
\(fn)" nil nil)
 | 
			
		||||
 | 
			
		||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "git-commit" '("git-commit-")))
 | 
			
		||||
 | 
			
		||||
;;;***
 | 
			
		||||
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; version-control: never
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; no-update-autoloads: t
 | 
			
		||||
;; coding: utf-8
 | 
			
		||||
;; End:
 | 
			
		||||
;;; git-commit-autoloads.el ends here
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
;;; -*- no-byte-compile: t -*-
 | 
			
		||||
(define-package "git-commit" "20200828.1753" "Edit Git commit messages" '((emacs "25.1") (dash "20200524") (transient "20200601") (with-editor "20200522")) :commit "f5ea9b2fe50642e305f43958027672cc1abedd8b" :keywords '("git" "tools" "vc") :maintainer '("Jonas Bernoulli" . "jonas@bernoul.li") :url "https://github.com/magit/magit")
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,358 +0,0 @@
 | 
			
		||||
Authors
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
The following people have contributed to Magit, including the
 | 
			
		||||
libraries `git-commit.el`, `magit-popup.el`, and `with-editor.el`
 | 
			
		||||
which are distributed as separate Elpa packages.
 | 
			
		||||
 | 
			
		||||
For statistics see https://magit.vc/stats/authors.html.
 | 
			
		||||
 | 
			
		||||
Names below are sorted alphabetically.
 | 
			
		||||
 | 
			
		||||
Author
 | 
			
		||||
------
 | 
			
		||||
 | 
			
		||||
- Marius Vollmer <marius.vollmer@gmail.com>
 | 
			
		||||
 | 
			
		||||
Maintainer
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
- Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
Developers
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
- Kyle Meyer <kyle@kyleam.com>
 | 
			
		||||
- Noam Postavsky <npostavs@users.sourceforge.net>
 | 
			
		||||
 | 
			
		||||
Retired Maintainers and Developers
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
- Nicolas Dudebout <nicolas.dudebout@gatech.edu>
 | 
			
		||||
- Peter J. Weisberg <pj@irregularexpressions.net>
 | 
			
		||||
- Pieter Praet <pieter@praet.org>
 | 
			
		||||
- Phil Jackson <phil@shellarchive.co.uk>
 | 
			
		||||
- Rémi Vanicat <vanicat@debian.org>
 | 
			
		||||
- Yann Hodique <yann.hodique@gmail.com>
 | 
			
		||||
 | 
			
		||||
Contributors
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
- Aaron Culich <aculich@gmail.com>
 | 
			
		||||
- Aaron Madlon-Kay <aaron@madlon-kay.com>
 | 
			
		||||
- Abdo Roig-Maranges <abdo.roig@gmail.com>
 | 
			
		||||
- Adam Benanti <0entropy@protonmail.com>
 | 
			
		||||
- Adam Kruszewski <adam@kruszewski.name>
 | 
			
		||||
- Adam Porter <adam@alphapapa.net>
 | 
			
		||||
- Adam Spiers <emacs@adamspiers.org>
 | 
			
		||||
- Adeodato Simó <dato@net.com.org.es>
 | 
			
		||||
- Ævar Arnfjörð Bjarmason <avarab@gmail.com>
 | 
			
		||||
- Alan Falloon <alan.falloon@gmail.com>
 | 
			
		||||
- Alban Gruin <alban@pa1ch.fr>
 | 
			
		||||
- Aleksey Uimanov <s9gf4ult@gmail.com>
 | 
			
		||||
- Alexander Gramiak <fice-t@protonmail.com>
 | 
			
		||||
- Alexander Miller <alexanderm@web.de>
 | 
			
		||||
- Alex Branham <alex.branham@gmail.com>
 | 
			
		||||
- Alex Dunn <adunn@ucsb.edu>
 | 
			
		||||
- Alexey Voinov <alexey.v.voinov@gmail.com>
 | 
			
		||||
- Alex Kost <alezost@gmail.com>
 | 
			
		||||
- Alex Ott <alexott@gmail.com>
 | 
			
		||||
- Allen <darkfeline@felesatra.moe>
 | 
			
		||||
- Allen Li <darkfeline@felesatra.moe>
 | 
			
		||||
- Andreas Fuchs <asf@boinkor.net>
 | 
			
		||||
- Andreas Liljeqvist <andreas.liljeqvist@robacks.se>
 | 
			
		||||
- Andreas Rottmann <a.rottmann@gmx.at>
 | 
			
		||||
- Andrei Chițu <andrei.chitu1@gmail.com>
 | 
			
		||||
- Andrew Eggenberger <andrew.eggenberger@gmail.com>
 | 
			
		||||
- Andrew Kirkpatrick <andrew.kirkpatrick@adelaide.edu.au>
 | 
			
		||||
- Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
 | 
			
		||||
- Andrey Smirnov <andrew.smirnov@gmail.com>
 | 
			
		||||
- Andriy Kmit' <dev@madand.net>
 | 
			
		||||
- Andy Sawyer <git@pureabstract.org>
 | 
			
		||||
- Aria Edmonds <aria@ar1as.space>
 | 
			
		||||
- Arialdo Martini <arialdomartini@gmail.com>
 | 
			
		||||
- Arnau Roig Ninerola <arnau.ninerola@outlook.com>
 | 
			
		||||
- Barak A. Pearlmutter <barak+git@pearlmutter.net>
 | 
			
		||||
- Bar Magal <bmagamb@gmail.com>
 | 
			
		||||
- Bart Bakker <bart@thesoftwarecraft.com>
 | 
			
		||||
- Basil L. Contovounesios <contovob@tcd.ie>
 | 
			
		||||
- Bastian Beischer <beischer@physik.rwth-aachen.de>
 | 
			
		||||
- Benjamin Motz <benjamin.motz@mailbox.org>
 | 
			
		||||
- Ben North <ben@redfrontdoor.org>
 | 
			
		||||
- Ben Walton <bwalton@artsci.utoronto.ca>
 | 
			
		||||
- Bob Uhl <buhl@zvelo.com>
 | 
			
		||||
- Bradley Wright <brad@intranation.com>
 | 
			
		||||
- Brandon W Maister <quodlibetor@gmail.com>
 | 
			
		||||
- Brian Leung <leungbk@mailfence.com>
 | 
			
		||||
- Brian Warner <warner@lothar.com>
 | 
			
		||||
- Bryan Shell <bryan.shell@orbitz.com>
 | 
			
		||||
- Buster Copley <buster@buster.me.uk>
 | 
			
		||||
- Carl Lieberman <liebermancarl@gmail.com>
 | 
			
		||||
- Chillar Anand <anand21nanda@gmail.com>
 | 
			
		||||
- Chris Bernard <cebernard@gmail.com>
 | 
			
		||||
- Chris Done <chrisdone@gmail.com>
 | 
			
		||||
- Chris LaRose <cjlarose@gmail.com>
 | 
			
		||||
- Chris Moore <dooglus@gmail.com>
 | 
			
		||||
- Chris Ring <chris@ringthis.com>
 | 
			
		||||
- Chris Shoemaker <chris@mojotech.com>
 | 
			
		||||
- Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
 | 
			
		||||
- Christian Kluge <ckfrakturfreak@web.de>
 | 
			
		||||
- Christophe Junke <junke.christophe@gmail.com>
 | 
			
		||||
- Christopher Monsanto <chris@monsan.to>
 | 
			
		||||
- Clément Pit-Claudel <clement.pitclaudel@live.com>
 | 
			
		||||
- Cornelius Mika <cornelius.mika@gmail.com>
 | 
			
		||||
- Craig Andera <candera@wangdera.com>
 | 
			
		||||
- Dale Hagglund <dale.hagglund@gmail.com>
 | 
			
		||||
- Damien Cassou <damien@cassou.me>
 | 
			
		||||
- Dan Davison <dandavison7@gmail.com>
 | 
			
		||||
- Dan Erikson <derikson3@gmail.com>
 | 
			
		||||
- Daniel Brockman <daniel@gointeractive.se>
 | 
			
		||||
- Daniel Farina <drfarina@acm.org>
 | 
			
		||||
- Daniel Gröber <daniel@dps.uibk.ac.at>
 | 
			
		||||
- Daniel Hackney <dan@haxney.org>
 | 
			
		||||
- Daniel Kraus <daniel@kraus.my>
 | 
			
		||||
- Daniel Mai <daniel@danielmai.net>
 | 
			
		||||
- Daniel Martín <mardani29@yahoo.es>
 | 
			
		||||
- Dan LaManna <dan.lamanna@gmail.com>
 | 
			
		||||
- Danny Zhu <dzhu@dzhu.us>
 | 
			
		||||
- Dato Simó <dato@net.com.org.es>
 | 
			
		||||
- David Abrahams <dave@boostpro.com>
 | 
			
		||||
- David Ellison <davidehellison@gmail.com>
 | 
			
		||||
- David Ellison <davide@voicebox.com>
 | 
			
		||||
- David Hull <david.hull@openx.com>
 | 
			
		||||
- David L. Rager <ragerdl@gmail.com>
 | 
			
		||||
- David Wallin <david.wallin@gmail.com>
 | 
			
		||||
- Dean Kariniemi <8913263+d3k4r@users.noreply.github.com>
 | 
			
		||||
- Dennis Paskorz <dennis@walltowall.com>
 | 
			
		||||
- Divye Kapoor <divye@google.com>
 | 
			
		||||
- Dominique Quatravaux <dominique.quatravaux@epfl.ch>
 | 
			
		||||
- Dominique Quatravaux <domq@google.com>
 | 
			
		||||
- Duianto Vebotci <vebotci@openmailbox.org>
 | 
			
		||||
- Eli Barzilay <eli@barzilay.org>
 | 
			
		||||
- Eric Davis <ed@npri.org>
 | 
			
		||||
- Eric <e.a.gebhart@gmail.com>
 | 
			
		||||
- Eric Prud'hommeaux <eric@w3.org>
 | 
			
		||||
- Eric Schulte <schulte.eric@gmail.com>
 | 
			
		||||
- Erik Anderson <erikbpanderson@gmail.com>
 | 
			
		||||
- Evan Torrie <etorrie@gmail.com>
 | 
			
		||||
- Evgkeni Sampelnikof <esabof@gmail.com>
 | 
			
		||||
- Eyal Lotem <eyal.lotem@gmail.com>
 | 
			
		||||
- Fabian Wiget <fabacino@gmail.com>
 | 
			
		||||
- Felix Geller <fgeller@gmail.com>
 | 
			
		||||
- Felix Yan <felixonmars@archlinux.org>
 | 
			
		||||
- Feng Li <fengli@blackmagicdesign.com>
 | 
			
		||||
- Florian Ragwitz <rafl@debian.org>
 | 
			
		||||
- Fritz Grabo <fritz.grabo@gmail.com>
 | 
			
		||||
- Fritz Stelzer <brotzeitmacher@gmail.com>
 | 
			
		||||
- Geoff Shannon <geoffpshannon@gmail.com>
 | 
			
		||||
- George Kadianakis <desnacked@gmail.com>
 | 
			
		||||
- Graham Clark <grclark@gmail.com>
 | 
			
		||||
- Graham Dobbins <gdobbins@protonmail.com>
 | 
			
		||||
- Greg A. Woods <woods@planix.com>
 | 
			
		||||
- Greg Lucas <greg@glucas.net>
 | 
			
		||||
- Gregory Heytings <ghe@sdf.org>
 | 
			
		||||
- Greg Sexton <gregsexton@gmail.com>
 | 
			
		||||
- Guillaume Martres <smarter@ubuntu.com>
 | 
			
		||||
- Hannu Koivisto <azure@iki.fi>
 | 
			
		||||
- Hans-Peter Deifel <hpdeifel@gmx.de>
 | 
			
		||||
- Hussein Ait-Lahcen <hussein.ait-lahcen@fretlink.com>
 | 
			
		||||
- Ian Eure <ian.eure@gmail.com>
 | 
			
		||||
- Ingo Lohmar <i.lohmar@gmail.com>
 | 
			
		||||
- Ioan-Adrian Ratiu <adi@adirat.com>
 | 
			
		||||
- Ivan Brennan <ivan.brennan@gmail.com>
 | 
			
		||||
- Jan Tatarik <jan.tatarik@xing.com>
 | 
			
		||||
- Jasper St. Pierre <jstpierre@mecheye.net>
 | 
			
		||||
- Jeff Bellegarde <jbellegarde@whitepages.com>
 | 
			
		||||
- Jeff Dairiki <dairiki@dairiki.org>
 | 
			
		||||
- Jeremy Meng <yumeng@microsoft.com>
 | 
			
		||||
- Jesse Alama <jesse.alama@gmail.com>
 | 
			
		||||
- Jim Blandy <jimb@red-bean.com>
 | 
			
		||||
- Joakim Jalap <JOJA@stoneridge.com>
 | 
			
		||||
- Johannes Altmanninger <aclopte@gmail.com>
 | 
			
		||||
- Johann Klähn <kljohann@gmail.com>
 | 
			
		||||
- John Mastro <john.b.mastro@gmail.com>
 | 
			
		||||
- John Morris <john@zultron.com>
 | 
			
		||||
- John Wiegley <johnw@newartisans.com>
 | 
			
		||||
- Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
- Jonas Galvão Xavier <jonas.agx@gmail.com>
 | 
			
		||||
- Jonathan Arnett <jonathan@scriptdrop.co>
 | 
			
		||||
- Jonathan del Strother <me@delstrother.com>
 | 
			
		||||
- Jonathan Leech-Pepin <jonathan.leechpepin@gmail.com>
 | 
			
		||||
- Jonathan Roes <jroes@jroes.net>
 | 
			
		||||
- Jon Vanderwijk <jonathn@github.com>
 | 
			
		||||
- Jordan Galby <gravemind2a@gmail.com>
 | 
			
		||||
- Jordan Greenberg <jordan@softwareslave.com>
 | 
			
		||||
- Josh Elsasser <jelsasser@appneta.com>
 | 
			
		||||
- Josiah Schwab <jschwab@gmail.com>
 | 
			
		||||
- Julien Danjou <julien@danjou.info>
 | 
			
		||||
- Justin Burkett <justin@burkett.cc>
 | 
			
		||||
- Justin Caratzas <justin.caratzas@gmail.com>
 | 
			
		||||
- Justin Guenther <jguenther@gmail.com>
 | 
			
		||||
- Justin Thomas <justin.thomas1@gmail.com>
 | 
			
		||||
- Kan-Ru Chen <kanru@kanru.info>
 | 
			
		||||
- Kenny Ballou <kballou@devnulllabs.io>
 | 
			
		||||
- Keshav Kini <keshav.kini@gmail.com>
 | 
			
		||||
- Kevin Brubeck Unhammer <unhammer@fsfe.org>
 | 
			
		||||
- Kevin J. Foley <kfoley15@gmail.com>
 | 
			
		||||
- Kévin Le Gouguec <kevin.legouguec@gmail.com>
 | 
			
		||||
- Kimberly Wolk <kimwolk@hotmail.com>
 | 
			
		||||
- Knut Olav Bøhmer <bohmer@gmail.com>
 | 
			
		||||
- Kyle Meyer <kyle@kyleam.com>
 | 
			
		||||
- Laurent Laffont <laurent.laffont@gmail.com>
 | 
			
		||||
- Laverne Schrock <laverne@schrock.email>
 | 
			
		||||
- Leandro Facchinetti <me@leafac.com>
 | 
			
		||||
- Lele Gaifax <lele@metapensiero.it>
 | 
			
		||||
- Leo Liu <sdl.web@gmail.com>
 | 
			
		||||
- Leonardo Etcheverry <leo@kalio.net>
 | 
			
		||||
- Leo Vivier <leo.vivier+dev@gmail.com>
 | 
			
		||||
- Lingchao Xin <douglarek@users.noreply.github.com>
 | 
			
		||||
- Li-Yun Chang <michael142536@gmail.com>
 | 
			
		||||
- Lluís Vilanova <vilanova@ac.upc.edu>
 | 
			
		||||
- Loic Dachary <loic@dachary.org>
 | 
			
		||||
- Louis Roché <louis@louisroche.net>
 | 
			
		||||
- Luís Oliveira <luismbo@gmail.com>
 | 
			
		||||
- Luke Amdor <luke.amdor@gmail.com>
 | 
			
		||||
- Magnus Malm <magnusmalm@gmail.com>
 | 
			
		||||
- Mak Kolybabi <mak@kolybabi.com>
 | 
			
		||||
- Manuel Vázquez Acosta <mva.led@gmail.com>
 | 
			
		||||
- Marcel Wolf <mwolf@ml1.net>
 | 
			
		||||
- Marc Herbert <marc.herbert@gmail.com>
 | 
			
		||||
- Marcin Bachry <hegel666@gmail.com>
 | 
			
		||||
- Marco Craveiro <marco.craveiro@gmail.com>
 | 
			
		||||
- Marco Wahl <marcowahlsoft@gmail.com>
 | 
			
		||||
- Marc Sherry <msherry@gmail.com>
 | 
			
		||||
- Marian Schubert <marian.schubert@gmail.com>
 | 
			
		||||
- Mario Rodas <marsam@users.noreply.github.com>
 | 
			
		||||
- Marius Vollmer <marius.vollmer@gmail.com>
 | 
			
		||||
- Mark Hepburn <Mark.Hepburn@csiro.au>
 | 
			
		||||
- Mark Karpov <markkarpov@opmbx.org>
 | 
			
		||||
- Mark Oteiza <mvoteiza@udel.edu>
 | 
			
		||||
- Matthew Fluet <matthew.fluet@gmail.com>
 | 
			
		||||
- Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
 | 
			
		||||
- Matus Goljer <dota.keys@gmail.com>
 | 
			
		||||
- Maxim Cournoyer <maxim.cournoyer@gmail.com>
 | 
			
		||||
- Michael Fogleman <michaelwfogleman@gmail.com>
 | 
			
		||||
- Michael Griffiths <mikey@cich.li>
 | 
			
		||||
- Michael Heerdegen <michael_heerdegen@web.de>
 | 
			
		||||
- Michal Sojka <sojkam1@fel.cvut.cz>
 | 
			
		||||
- Miciah Masters <miciah.masters@gmail.com>
 | 
			
		||||
- Miles Bader <miles@gnu.org>
 | 
			
		||||
- Miloš Mošić <mosic.milos@gmail.com>
 | 
			
		||||
- Mitchel Humpherys <mitch.special@gmail.com>
 | 
			
		||||
- Moritz Bunkus <moritz@bunkus.org>
 | 
			
		||||
- Naoya Yamashita <conao3@gmail.com>
 | 
			
		||||
- Natalie Weizenbaum <nex342@gmail.com>
 | 
			
		||||
- Nguyễn Tuấn Anh <ubolonton@gmail.com>
 | 
			
		||||
- Nic Ferier <nic@ferrier.me.uk>
 | 
			
		||||
- Nick Alcock <nick.alcock@oracle.com>
 | 
			
		||||
- Nick Alexander <nalexander@mozilla.com>
 | 
			
		||||
- Nick Dimiduk <ndimiduk@gmail.com>
 | 
			
		||||
- Nicklas Lindgren <nili@gulmohar.se>
 | 
			
		||||
- Nicolas Dudebout <nicolas.dudebout@gatech.edu>
 | 
			
		||||
- Nicolas Petton <nicolas@petton.fr>
 | 
			
		||||
- Nicolas Richard <theonewiththeevillook@yahoo.fr>
 | 
			
		||||
- Nikolay Martynov <mar.kolya@gmail.com>
 | 
			
		||||
- Noam Postavsky <npostavs@users.sourceforge.net>
 | 
			
		||||
- N. Troy de Freitas <me@ntdef.com>
 | 
			
		||||
- Ole Arndt <oliver.arndt@cegedim.com>
 | 
			
		||||
- Oleh Krehel <ohwoeowho@gmail.com>
 | 
			
		||||
- Orivej Desh <orivej@gmx.fr>
 | 
			
		||||
- Óscar Fuentes <ofv@wanadoo.es>
 | 
			
		||||
- Paul Stadig <paul@stadig.name>
 | 
			
		||||
- Pavel Holejsovsky <pavel.holejsovsky@upek.com>
 | 
			
		||||
- Pekka Pessi <nospam@pessi.fi>
 | 
			
		||||
- Peter Eisentraut <peter@eisentraut.org>
 | 
			
		||||
- Peter Jaros <peter.a.jaros@gmail.com>
 | 
			
		||||
- Peter J. Weisberg <pj@irregularexpressions.net>
 | 
			
		||||
- Peter Vasil <mail@petervasil.net>
 | 
			
		||||
- Philippe Vaucher <philippe.vaucher@gmail.com>
 | 
			
		||||
- Philipp Haselwarter <philipp@haselwarter.org>
 | 
			
		||||
- Philipp Stephani <phst@google.com>
 | 
			
		||||
- Philip Weaver <philip.weaver@gmail.com>
 | 
			
		||||
- Phil Jackson <phil@shellarchive.co.uk>
 | 
			
		||||
- Phil Sainty <phil@catalyst.net.nz>
 | 
			
		||||
- Pierre Neidhardt <ambrevar@gmail.com>
 | 
			
		||||
- Pieter Praet <pieter@praet.org>
 | 
			
		||||
- Prathamesh Sonpatki <csonpatki@gmail.com>
 | 
			
		||||
- rabio <rabiodev@o2.pl>
 | 
			
		||||
- Radon Rosborough <radon.neon@gmail.com>
 | 
			
		||||
- Rafael Laboissiere <rafael@laboissiere.net>
 | 
			
		||||
- Raimon Grau <raimon@3scale.net>
 | 
			
		||||
- Ramkumar Ramachandra <artagnon@gmail.com>
 | 
			
		||||
- Remco van 't Veer <rwvtveer@xs4all.nl>
 | 
			
		||||
- Rémi Vanicat <vanicat@debian.org>
 | 
			
		||||
- René Stadler <mail@renestadler.de>
 | 
			
		||||
- Richard Kim <emacs18@gmail.com>
 | 
			
		||||
- Robert Boone <robo4288@gmail.com>
 | 
			
		||||
- Robin Green <greenrd@greenrd.org>
 | 
			
		||||
- Roey Darwish Dror <roey.ghost@gmail.com>
 | 
			
		||||
- Roger Crew <crew@cs.stanford.edu>
 | 
			
		||||
- Romain Francoise <romain@orebokech.com>
 | 
			
		||||
- Ron Parker <rparker@a123systems.com>
 | 
			
		||||
- Roy Crihfield <rscrihf@gmail.com>
 | 
			
		||||
- Rüdiger Sonderfeld <ruediger@c-plusplus.net>
 | 
			
		||||
- Russell Black <black.russell@gmail.com>
 | 
			
		||||
- Ryan C. Thompson <rct@thompsonclan.org>
 | 
			
		||||
- Samuel Bronson <naesten@gmail.com>
 | 
			
		||||
- Samuel W. Flint <swflint@flintfam.org>
 | 
			
		||||
- Sanjoy Das <sanjoy@playingwithpointers.com>
 | 
			
		||||
- Sean Allred <code@seanallred.com>
 | 
			
		||||
- Sean Bryant <sbryant@hackinggibsons.com>
 | 
			
		||||
- Sean Whitton <spwhitton@spwhitton.name>
 | 
			
		||||
- Sebastian Wiesner <lunaryorn@gmail.com>
 | 
			
		||||
- Sébastien Gross <seb@chezwam.org>
 | 
			
		||||
- Seong-Kook Shin <cinsky@gmail.com>
 | 
			
		||||
- Sergey Pashinin <sergey@pashinin.com>
 | 
			
		||||
- Sergey Vinokurov <serg.foo@gmail.com>
 | 
			
		||||
- Servilio Afre Puentes <afrepues@mcmaster.ca>
 | 
			
		||||
- Silent Sphere <silentsphere110@gmail.com>
 | 
			
		||||
- Štěpán Němec <stepnem@gmail.com>
 | 
			
		||||
- Steven Chow <steve@myfreestuffapp.com>
 | 
			
		||||
- Steven E. Harris <seh@panix.com>
 | 
			
		||||
- Steven Thomas <sthomas314@gmail.com>
 | 
			
		||||
- Steven Vancoillie <steven.vancoillie@runbox.com>
 | 
			
		||||
- Steve Purcell <steve@sanityinc.com>
 | 
			
		||||
- Suhail Shergill <suhailshergill@gmail.com>
 | 
			
		||||
- Sylvain Rousseau <thisirs@gmail.com>
 | 
			
		||||
- Syohei Yoshida <syohex@gmail.com>
 | 
			
		||||
- Takafumi Arakaki <aka.tkf@gmail.com>
 | 
			
		||||
- Tassilo Horn <tsdh@gnu.org>
 | 
			
		||||
- Teemu Likonen <tlikonen@iki.fi>
 | 
			
		||||
- Teruki Shigitani <teruki.shigitani@gmail.com>
 | 
			
		||||
- Thierry Volpiatto <thierry.volpiatto@gmail.com>
 | 
			
		||||
- Thomas A Caswell <tcaswell@gmail.com>
 | 
			
		||||
- Thomas Fini Hansen <xen@xen.dk>
 | 
			
		||||
- Thomas Frössman <thomasf@jossystem.se>
 | 
			
		||||
- Thomas Jost <thomas.jost@gmail.com>
 | 
			
		||||
- Thomas Riccardi <riccardi.thomas@gmail.com>
 | 
			
		||||
- Tibor Simko <tibor.simko@cern.ch>
 | 
			
		||||
- Timo Juhani Lindfors <timo.lindfors@iki.fi>
 | 
			
		||||
- Tim Perkins <tprk77@gmail.com>
 | 
			
		||||
- Tim Wraight <tim@wraight.net>
 | 
			
		||||
- Ting-Yu Lin <aethanyc@gmail.com>
 | 
			
		||||
- Tom Feist <shabble@metavore.org>
 | 
			
		||||
- Topi Miettinen <toiwoton@gmail.com>
 | 
			
		||||
- Troy Hinckley <t.macman@gmail.com>
 | 
			
		||||
- Tsuyoshi Kitamoto <tsuyoshi.kitamoto@gmail.com>
 | 
			
		||||
- Tunc Uzlu <bb2020@users.noreply.github.com>
 | 
			
		||||
- Vineet Naik <vineet@helpshift.com>
 | 
			
		||||
- Vitaly Ostashov <hotosho@yandex-team.ru>
 | 
			
		||||
- Vladimir Panteleev <git@thecybershadow.net>
 | 
			
		||||
- Vladimir Sedach <vas@oneofus.la>
 | 
			
		||||
- Wei Huang <weih@opera.com>
 | 
			
		||||
- Wilfred Hughes <me@wilfred.me.uk>
 | 
			
		||||
- Win Treese <treese@acm.org>
 | 
			
		||||
- Wojciech Siewierski <wojciech@siewierski.eu>
 | 
			
		||||
- Wouter Bolsterlee <wouter@bolsterl.ee>
 | 
			
		||||
- Xavier Noria <fxn@hashref.com>
 | 
			
		||||
- Xu Chunyang <mail@xuchunyang.me>
 | 
			
		||||
- Yann Herklotz <git@yannherklotz.com>
 | 
			
		||||
- Yann Hodique <yann.hodique@gmail.com>
 | 
			
		||||
- Ynilu <ynilu.chang@gmail.com>
 | 
			
		||||
- York Zhao <gtdplatform@gmail.com>
 | 
			
		||||
- Yuichi Higashi <aaa707b@gmail.com>
 | 
			
		||||
- Yuri Khan <yurivkhan@gmail.com>
 | 
			
		||||
- Zach Latta <zach@zachlatta.com>
 | 
			
		||||
- zakora <zakora@users.noreply.github.com>
 | 
			
		||||
- Zhu Zihao <all_but_last@163.com>
 | 
			
		||||
- zilongshanren <guanghui8827@126.com>
 | 
			
		||||
@@ -1,676 +0,0 @@
 | 
			
		||||
 | 
			
		||||
		    GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
		       Version 3, 29 June 2007
 | 
			
		||||
 | 
			
		||||
 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 | 
			
		||||
 Everyone is permitted to copy and distribute verbatim copies
 | 
			
		||||
 of this license document, but changing it is not allowed.
 | 
			
		||||
 | 
			
		||||
			    Preamble
 | 
			
		||||
 | 
			
		||||
  The GNU General Public License is a free, copyleft license for
 | 
			
		||||
software and other kinds of works.
 | 
			
		||||
 | 
			
		||||
  The licenses for most software and other practical works are designed
 | 
			
		||||
to take away your freedom to share and change the works.  By contrast,
 | 
			
		||||
the GNU General Public License is intended to guarantee your freedom to
 | 
			
		||||
share and change all versions of a program--to make sure it remains free
 | 
			
		||||
software for all its users.  We, the Free Software Foundation, use the
 | 
			
		||||
GNU General Public License for most of our software; it applies also to
 | 
			
		||||
any other work released this way by its authors.  You can apply it to
 | 
			
		||||
your programs, too.
 | 
			
		||||
 | 
			
		||||
  When we speak of free software, we are referring to freedom, not
 | 
			
		||||
price.  Our General Public Licenses are designed to make sure that you
 | 
			
		||||
have the freedom to distribute copies of free software (and charge for
 | 
			
		||||
them if you wish), that you receive source code or can get it if you
 | 
			
		||||
want it, that you can change the software or use pieces of it in new
 | 
			
		||||
free programs, and that you know you can do these things.
 | 
			
		||||
 | 
			
		||||
  To protect your rights, we need to prevent others from denying you
 | 
			
		||||
these rights or asking you to surrender the rights.  Therefore, you have
 | 
			
		||||
certain responsibilities if you distribute copies of the software, or if
 | 
			
		||||
you modify it: responsibilities to respect the freedom of others.
 | 
			
		||||
 | 
			
		||||
  For example, if you distribute copies of such a program, whether
 | 
			
		||||
gratis or for a fee, you must pass on to the recipients the same
 | 
			
		||||
freedoms that you received.  You must make sure that they, too, receive
 | 
			
		||||
or can get the source code.  And you must show them these terms so they
 | 
			
		||||
know their rights.
 | 
			
		||||
 | 
			
		||||
  Developers that use the GNU GPL protect your rights with two steps:
 | 
			
		||||
(1) assert copyright on the software, and (2) offer you this License
 | 
			
		||||
giving you legal permission to copy, distribute and/or modify it.
 | 
			
		||||
 | 
			
		||||
  For the developers' and authors' protection, the GPL clearly explains
 | 
			
		||||
that there is no warranty for this free software.  For both users' and
 | 
			
		||||
authors' sake, the GPL requires that modified versions be marked as
 | 
			
		||||
changed, so that their problems will not be attributed erroneously to
 | 
			
		||||
authors of previous versions.
 | 
			
		||||
 | 
			
		||||
  Some devices are designed to deny users access to install or run
 | 
			
		||||
modified versions of the software inside them, although the manufacturer
 | 
			
		||||
can do so.  This is fundamentally incompatible with the aim of
 | 
			
		||||
protecting users' freedom to change the software.  The systematic
 | 
			
		||||
pattern of such abuse occurs in the area of products for individuals to
 | 
			
		||||
use, which is precisely where it is most unacceptable.  Therefore, we
 | 
			
		||||
have designed this version of the GPL to prohibit the practice for those
 | 
			
		||||
products.  If such problems arise substantially in other domains, we
 | 
			
		||||
stand ready to extend this provision to those domains in future versions
 | 
			
		||||
of the GPL, as needed to protect the freedom of users.
 | 
			
		||||
 | 
			
		||||
  Finally, every program is threatened constantly by software patents.
 | 
			
		||||
States should not allow patents to restrict development and use of
 | 
			
		||||
software on general-purpose computers, but in those that do, we wish to
 | 
			
		||||
avoid the special danger that patents applied to a free program could
 | 
			
		||||
make it effectively proprietary.  To prevent this, the GPL assures that
 | 
			
		||||
patents cannot be used to render the program non-free.
 | 
			
		||||
 | 
			
		||||
  The precise terms and conditions for copying, distribution and
 | 
			
		||||
modification follow.
 | 
			
		||||
 | 
			
		||||
		       TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
  0. Definitions.
 | 
			
		||||
 | 
			
		||||
  "This License" refers to version 3 of the GNU General Public License.
 | 
			
		||||
 | 
			
		||||
  "Copyright" also means copyright-like laws that apply to other kinds of
 | 
			
		||||
works, such as semiconductor masks.
 | 
			
		||||
 
 | 
			
		||||
  "The Program" refers to any copyrightable work licensed under this
 | 
			
		||||
License.  Each licensee is addressed as "you".  "Licensees" and
 | 
			
		||||
"recipients" may be individuals or organizations.
 | 
			
		||||
 | 
			
		||||
  To "modify" a work means to copy from or adapt all or part of the work
 | 
			
		||||
in a fashion requiring copyright permission, other than the making of an
 | 
			
		||||
exact copy.  The resulting work is called a "modified version" of the
 | 
			
		||||
earlier work or a work "based on" the earlier work.
 | 
			
		||||
 | 
			
		||||
  A "covered work" means either the unmodified Program or a work based
 | 
			
		||||
on the Program.
 | 
			
		||||
 | 
			
		||||
  To "propagate" a work means to do anything with it that, without
 | 
			
		||||
permission, would make you directly or secondarily liable for
 | 
			
		||||
infringement under applicable copyright law, except executing it on a
 | 
			
		||||
computer or modifying a private copy.  Propagation includes copying,
 | 
			
		||||
distribution (with or without modification), making available to the
 | 
			
		||||
public, and in some countries other activities as well.
 | 
			
		||||
 | 
			
		||||
  To "convey" a work means any kind of propagation that enables other
 | 
			
		||||
parties to make or receive copies.  Mere interaction with a user through
 | 
			
		||||
a computer network, with no transfer of a copy, is not conveying.
 | 
			
		||||
 | 
			
		||||
  An interactive user interface displays "Appropriate Legal Notices"
 | 
			
		||||
to the extent that it includes a convenient and prominently visible
 | 
			
		||||
feature that (1) displays an appropriate copyright notice, and (2)
 | 
			
		||||
tells the user that there is no warranty for the work (except to the
 | 
			
		||||
extent that warranties are provided), that licensees may convey the
 | 
			
		||||
work under this License, and how to view a copy of this License.  If
 | 
			
		||||
the interface presents a list of user commands or options, such as a
 | 
			
		||||
menu, a prominent item in the list meets this criterion.
 | 
			
		||||
 | 
			
		||||
  1. Source Code.
 | 
			
		||||
 | 
			
		||||
  The "source code" for a work means the preferred form of the work
 | 
			
		||||
for making modifications to it.  "Object code" means any non-source
 | 
			
		||||
form of a work.
 | 
			
		||||
 | 
			
		||||
  A "Standard Interface" means an interface that either is an official
 | 
			
		||||
standard defined by a recognized standards body, or, in the case of
 | 
			
		||||
interfaces specified for a particular programming language, one that
 | 
			
		||||
is widely used among developers working in that language.
 | 
			
		||||
 | 
			
		||||
  The "System Libraries" of an executable work include anything, other
 | 
			
		||||
than the work as a whole, that (a) is included in the normal form of
 | 
			
		||||
packaging a Major Component, but which is not part of that Major
 | 
			
		||||
Component, and (b) serves only to enable use of the work with that
 | 
			
		||||
Major Component, or to implement a Standard Interface for which an
 | 
			
		||||
implementation is available to the public in source code form.  A
 | 
			
		||||
"Major Component", in this context, means a major essential component
 | 
			
		||||
(kernel, window system, and so on) of the specific operating system
 | 
			
		||||
(if any) on which the executable work runs, or a compiler used to
 | 
			
		||||
produce the work, or an object code interpreter used to run it.
 | 
			
		||||
 | 
			
		||||
  The "Corresponding Source" for a work in object code form means all
 | 
			
		||||
the source code needed to generate, install, and (for an executable
 | 
			
		||||
work) run the object code and to modify the work, including scripts to
 | 
			
		||||
control those activities.  However, it does not include the work's
 | 
			
		||||
System Libraries, or general-purpose tools or generally available free
 | 
			
		||||
programs which are used unmodified in performing those activities but
 | 
			
		||||
which are not part of the work.  For example, Corresponding Source
 | 
			
		||||
includes interface definition files associated with source files for
 | 
			
		||||
the work, and the source code for shared libraries and dynamically
 | 
			
		||||
linked subprograms that the work is specifically designed to require,
 | 
			
		||||
such as by intimate data communication or control flow between those
 | 
			
		||||
subprograms and other parts of the work.
 | 
			
		||||
 | 
			
		||||
  The Corresponding Source need not include anything that users
 | 
			
		||||
can regenerate automatically from other parts of the Corresponding
 | 
			
		||||
Source.
 | 
			
		||||
 | 
			
		||||
  The Corresponding Source for a work in source code form is that
 | 
			
		||||
same work.
 | 
			
		||||
 | 
			
		||||
  2. Basic Permissions.
 | 
			
		||||
 | 
			
		||||
  All rights granted under this License are granted for the term of
 | 
			
		||||
copyright on the Program, and are irrevocable provided the stated
 | 
			
		||||
conditions are met.  This License explicitly affirms your unlimited
 | 
			
		||||
permission to run the unmodified Program.  The output from running a
 | 
			
		||||
covered work is covered by this License only if the output, given its
 | 
			
		||||
content, constitutes a covered work.  This License acknowledges your
 | 
			
		||||
rights of fair use or other equivalent, as provided by copyright law.
 | 
			
		||||
 | 
			
		||||
  You may make, run and propagate covered works that you do not
 | 
			
		||||
convey, without conditions so long as your license otherwise remains
 | 
			
		||||
in force.  You may convey covered works to others for the sole purpose
 | 
			
		||||
of having them make modifications exclusively for you, or provide you
 | 
			
		||||
with facilities for running those works, provided that you comply with
 | 
			
		||||
the terms of this License in conveying all material for which you do
 | 
			
		||||
not control copyright.  Those thus making or running the covered works
 | 
			
		||||
for you must do so exclusively on your behalf, under your direction
 | 
			
		||||
and control, on terms that prohibit them from making any copies of
 | 
			
		||||
your copyrighted material outside their relationship with you.
 | 
			
		||||
 | 
			
		||||
  Conveying under any other circumstances is permitted solely under
 | 
			
		||||
the conditions stated below.  Sublicensing is not allowed; section 10
 | 
			
		||||
makes it unnecessary.
 | 
			
		||||
 | 
			
		||||
  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 | 
			
		||||
 | 
			
		||||
  No covered work shall be deemed part of an effective technological
 | 
			
		||||
measure under any applicable law fulfilling obligations under article
 | 
			
		||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
 | 
			
		||||
similar laws prohibiting or restricting circumvention of such
 | 
			
		||||
measures.
 | 
			
		||||
 | 
			
		||||
  When you convey a covered work, you waive any legal power to forbid
 | 
			
		||||
circumvention of technological measures to the extent such circumvention
 | 
			
		||||
is effected by exercising rights under this License with respect to
 | 
			
		||||
the covered work, and you disclaim any intention to limit operation or
 | 
			
		||||
modification of the work as a means of enforcing, against the work's
 | 
			
		||||
users, your or third parties' legal rights to forbid circumvention of
 | 
			
		||||
technological measures.
 | 
			
		||||
 | 
			
		||||
  4. Conveying Verbatim Copies.
 | 
			
		||||
 | 
			
		||||
  You may convey verbatim copies of the Program's source code as you
 | 
			
		||||
receive it, in any medium, provided that you conspicuously and
 | 
			
		||||
appropriately publish on each copy an appropriate copyright notice;
 | 
			
		||||
keep intact all notices stating that this License and any
 | 
			
		||||
non-permissive terms added in accord with section 7 apply to the code;
 | 
			
		||||
keep intact all notices of the absence of any warranty; and give all
 | 
			
		||||
recipients a copy of this License along with the Program.
 | 
			
		||||
 | 
			
		||||
  You may charge any price or no price for each copy that you convey,
 | 
			
		||||
and you may offer support or warranty protection for a fee.
 | 
			
		||||
 | 
			
		||||
  5. Conveying Modified Source Versions.
 | 
			
		||||
 | 
			
		||||
  You may convey a work based on the Program, or the modifications to
 | 
			
		||||
produce it from the Program, in the form of source code under the
 | 
			
		||||
terms of section 4, provided that you also meet all of these conditions:
 | 
			
		||||
 | 
			
		||||
    a) The work must carry prominent notices stating that you modified
 | 
			
		||||
    it, and giving a relevant date.
 | 
			
		||||
 | 
			
		||||
    b) The work must carry prominent notices stating that it is
 | 
			
		||||
    released under this License and any conditions added under section
 | 
			
		||||
    7.  This requirement modifies the requirement in section 4 to
 | 
			
		||||
    "keep intact all notices".
 | 
			
		||||
 | 
			
		||||
    c) You must license the entire work, as a whole, under this
 | 
			
		||||
    License to anyone who comes into possession of a copy.  This
 | 
			
		||||
    License will therefore apply, along with any applicable section 7
 | 
			
		||||
    additional terms, to the whole of the work, and all its parts,
 | 
			
		||||
    regardless of how they are packaged.  This License gives no
 | 
			
		||||
    permission to license the work in any other way, but it does not
 | 
			
		||||
    invalidate such permission if you have separately received it.
 | 
			
		||||
 | 
			
		||||
    d) If the work has interactive user interfaces, each must display
 | 
			
		||||
    Appropriate Legal Notices; however, if the Program has interactive
 | 
			
		||||
    interfaces that do not display Appropriate Legal Notices, your
 | 
			
		||||
    work need not make them do so.
 | 
			
		||||
 | 
			
		||||
  A compilation of a covered work with other separate and independent
 | 
			
		||||
works, which are not by their nature extensions of the covered work,
 | 
			
		||||
and which are not combined with it such as to form a larger program,
 | 
			
		||||
in or on a volume of a storage or distribution medium, is called an
 | 
			
		||||
"aggregate" if the compilation and its resulting copyright are not
 | 
			
		||||
used to limit the access or legal rights of the compilation's users
 | 
			
		||||
beyond what the individual works permit.  Inclusion of a covered work
 | 
			
		||||
in an aggregate does not cause this License to apply to the other
 | 
			
		||||
parts of the aggregate.
 | 
			
		||||
 | 
			
		||||
  6. Conveying Non-Source Forms.
 | 
			
		||||
 | 
			
		||||
  You may convey a covered work in object code form under the terms
 | 
			
		||||
of sections 4 and 5, provided that you also convey the
 | 
			
		||||
machine-readable Corresponding Source under the terms of this License,
 | 
			
		||||
in one of these ways:
 | 
			
		||||
 | 
			
		||||
    a) Convey the object code in, or embodied in, a physical product
 | 
			
		||||
    (including a physical distribution medium), accompanied by the
 | 
			
		||||
    Corresponding Source fixed on a durable physical medium
 | 
			
		||||
    customarily used for software interchange.
 | 
			
		||||
 | 
			
		||||
    b) Convey the object code in, or embodied in, a physical product
 | 
			
		||||
    (including a physical distribution medium), accompanied by a
 | 
			
		||||
    written offer, valid for at least three years and valid for as
 | 
			
		||||
    long as you offer spare parts or customer support for that product
 | 
			
		||||
    model, to give anyone who possesses the object code either (1) a
 | 
			
		||||
    copy of the Corresponding Source for all the software in the
 | 
			
		||||
    product that is covered by this License, on a durable physical
 | 
			
		||||
    medium customarily used for software interchange, for a price no
 | 
			
		||||
    more than your reasonable cost of physically performing this
 | 
			
		||||
    conveying of source, or (2) access to copy the
 | 
			
		||||
    Corresponding Source from a network server at no charge.
 | 
			
		||||
 | 
			
		||||
    c) Convey individual copies of the object code with a copy of the
 | 
			
		||||
    written offer to provide the Corresponding Source.  This
 | 
			
		||||
    alternative is allowed only occasionally and noncommercially, and
 | 
			
		||||
    only if you received the object code with such an offer, in accord
 | 
			
		||||
    with subsection 6b.
 | 
			
		||||
 | 
			
		||||
    d) Convey the object code by offering access from a designated
 | 
			
		||||
    place (gratis or for a charge), and offer equivalent access to the
 | 
			
		||||
    Corresponding Source in the same way through the same place at no
 | 
			
		||||
    further charge.  You need not require recipients to copy the
 | 
			
		||||
    Corresponding Source along with the object code.  If the place to
 | 
			
		||||
    copy the object code is a network server, the Corresponding Source
 | 
			
		||||
    may be on a different server (operated by you or a third party)
 | 
			
		||||
    that supports equivalent copying facilities, provided you maintain
 | 
			
		||||
    clear directions next to the object code saying where to find the
 | 
			
		||||
    Corresponding Source.  Regardless of what server hosts the
 | 
			
		||||
    Corresponding Source, you remain obligated to ensure that it is
 | 
			
		||||
    available for as long as needed to satisfy these requirements.
 | 
			
		||||
 | 
			
		||||
    e) Convey the object code using peer-to-peer transmission, provided
 | 
			
		||||
    you inform other peers where the object code and Corresponding
 | 
			
		||||
    Source of the work are being offered to the general public at no
 | 
			
		||||
    charge under subsection 6d.
 | 
			
		||||
 | 
			
		||||
  A separable portion of the object code, whose source code is excluded
 | 
			
		||||
from the Corresponding Source as a System Library, need not be
 | 
			
		||||
included in conveying the object code work.
 | 
			
		||||
 | 
			
		||||
  A "User Product" is either (1) a "consumer product", which means any
 | 
			
		||||
tangible personal property which is normally used for personal, family,
 | 
			
		||||
or household purposes, or (2) anything designed or sold for incorporation
 | 
			
		||||
into a dwelling.  In determining whether a product is a consumer product,
 | 
			
		||||
doubtful cases shall be resolved in favor of coverage.  For a particular
 | 
			
		||||
product received by a particular user, "normally used" refers to a
 | 
			
		||||
typical or common use of that class of product, regardless of the status
 | 
			
		||||
of the particular user or of the way in which the particular user
 | 
			
		||||
actually uses, or expects or is expected to use, the product.  A product
 | 
			
		||||
is a consumer product regardless of whether the product has substantial
 | 
			
		||||
commercial, industrial or non-consumer uses, unless such uses represent
 | 
			
		||||
the only significant mode of use of the product.
 | 
			
		||||
 | 
			
		||||
  "Installation Information" for a User Product means any methods,
 | 
			
		||||
procedures, authorization keys, or other information required to install
 | 
			
		||||
and execute modified versions of a covered work in that User Product from
 | 
			
		||||
a modified version of its Corresponding Source.  The information must
 | 
			
		||||
suffice to ensure that the continued functioning of the modified object
 | 
			
		||||
code is in no case prevented or interfered with solely because
 | 
			
		||||
modification has been made.
 | 
			
		||||
 | 
			
		||||
  If you convey an object code work under this section in, or with, or
 | 
			
		||||
specifically for use in, a User Product, and the conveying occurs as
 | 
			
		||||
part of a transaction in which the right of possession and use of the
 | 
			
		||||
User Product is transferred to the recipient in perpetuity or for a
 | 
			
		||||
fixed term (regardless of how the transaction is characterized), the
 | 
			
		||||
Corresponding Source conveyed under this section must be accompanied
 | 
			
		||||
by the Installation Information.  But this requirement does not apply
 | 
			
		||||
if neither you nor any third party retains the ability to install
 | 
			
		||||
modified object code on the User Product (for example, the work has
 | 
			
		||||
been installed in ROM).
 | 
			
		||||
 | 
			
		||||
  The requirement to provide Installation Information does not include a
 | 
			
		||||
requirement to continue to provide support service, warranty, or updates
 | 
			
		||||
for a work that has been modified or installed by the recipient, or for
 | 
			
		||||
the User Product in which it has been modified or installed.  Access to a
 | 
			
		||||
network may be denied when the modification itself materially and
 | 
			
		||||
adversely affects the operation of the network or violates the rules and
 | 
			
		||||
protocols for communication across the network.
 | 
			
		||||
 | 
			
		||||
  Corresponding Source conveyed, and Installation Information provided,
 | 
			
		||||
in accord with this section must be in a format that is publicly
 | 
			
		||||
documented (and with an implementation available to the public in
 | 
			
		||||
source code form), and must require no special password or key for
 | 
			
		||||
unpacking, reading or copying.
 | 
			
		||||
 | 
			
		||||
  7. Additional Terms.
 | 
			
		||||
 | 
			
		||||
  "Additional permissions" are terms that supplement the terms of this
 | 
			
		||||
License by making exceptions from one or more of its conditions.
 | 
			
		||||
Additional permissions that are applicable to the entire Program shall
 | 
			
		||||
be treated as though they were included in this License, to the extent
 | 
			
		||||
that they are valid under applicable law.  If additional permissions
 | 
			
		||||
apply only to part of the Program, that part may be used separately
 | 
			
		||||
under those permissions, but the entire Program remains governed by
 | 
			
		||||
this License without regard to the additional permissions.
 | 
			
		||||
 | 
			
		||||
  When you convey a copy of a covered work, you may at your option
 | 
			
		||||
remove any additional permissions from that copy, or from any part of
 | 
			
		||||
it.  (Additional permissions may be written to require their own
 | 
			
		||||
removal in certain cases when you modify the work.)  You may place
 | 
			
		||||
additional permissions on material, added by you to a covered work,
 | 
			
		||||
for which you have or can give appropriate copyright permission.
 | 
			
		||||
 | 
			
		||||
  Notwithstanding any other provision of this License, for material you
 | 
			
		||||
add to a covered work, you may (if authorized by the copyright holders of
 | 
			
		||||
that material) supplement the terms of this License with terms:
 | 
			
		||||
 | 
			
		||||
    a) Disclaiming warranty or limiting liability differently from the
 | 
			
		||||
    terms of sections 15 and 16 of this License; or
 | 
			
		||||
 | 
			
		||||
    b) Requiring preservation of specified reasonable legal notices or
 | 
			
		||||
    author attributions in that material or in the Appropriate Legal
 | 
			
		||||
    Notices displayed by works containing it; or
 | 
			
		||||
 | 
			
		||||
    c) Prohibiting misrepresentation of the origin of that material, or
 | 
			
		||||
    requiring that modified versions of such material be marked in
 | 
			
		||||
    reasonable ways as different from the original version; or
 | 
			
		||||
 | 
			
		||||
    d) Limiting the use for publicity purposes of names of licensors or
 | 
			
		||||
    authors of the material; or
 | 
			
		||||
 | 
			
		||||
    e) Declining to grant rights under trademark law for use of some
 | 
			
		||||
    trade names, trademarks, or service marks; or
 | 
			
		||||
 | 
			
		||||
    f) Requiring indemnification of licensors and authors of that
 | 
			
		||||
    material by anyone who conveys the material (or modified versions of
 | 
			
		||||
    it) with contractual assumptions of liability to the recipient, for
 | 
			
		||||
    any liability that these contractual assumptions directly impose on
 | 
			
		||||
    those licensors and authors.
 | 
			
		||||
 | 
			
		||||
  All other non-permissive additional terms are considered "further
 | 
			
		||||
restrictions" within the meaning of section 10.  If the Program as you
 | 
			
		||||
received it, or any part of it, contains a notice stating that it is
 | 
			
		||||
governed by this License along with a term that is a further
 | 
			
		||||
restriction, you may remove that term.  If a license document contains
 | 
			
		||||
a further restriction but permits relicensing or conveying under this
 | 
			
		||||
License, you may add to a covered work material governed by the terms
 | 
			
		||||
of that license document, provided that the further restriction does
 | 
			
		||||
not survive such relicensing or conveying.
 | 
			
		||||
 | 
			
		||||
  If you add terms to a covered work in accord with this section, you
 | 
			
		||||
must place, in the relevant source files, a statement of the
 | 
			
		||||
additional terms that apply to those files, or a notice indicating
 | 
			
		||||
where to find the applicable terms.
 | 
			
		||||
 | 
			
		||||
  Additional terms, permissive or non-permissive, may be stated in the
 | 
			
		||||
form of a separately written license, or stated as exceptions;
 | 
			
		||||
the above requirements apply either way.
 | 
			
		||||
 | 
			
		||||
  8. Termination.
 | 
			
		||||
 | 
			
		||||
  You may not propagate or modify a covered work except as expressly
 | 
			
		||||
provided under this License.  Any attempt otherwise to propagate or
 | 
			
		||||
modify it is void, and will automatically terminate your rights under
 | 
			
		||||
this License (including any patent licenses granted under the third
 | 
			
		||||
paragraph of section 11).
 | 
			
		||||
 | 
			
		||||
  However, if you cease all violation of this License, then your
 | 
			
		||||
license from a particular copyright holder is reinstated (a)
 | 
			
		||||
provisionally, unless and until the copyright holder explicitly and
 | 
			
		||||
finally terminates your license, and (b) permanently, if the copyright
 | 
			
		||||
holder fails to notify you of the violation by some reasonable means
 | 
			
		||||
prior to 60 days after the cessation.
 | 
			
		||||
 | 
			
		||||
  Moreover, your license from a particular copyright holder is
 | 
			
		||||
reinstated permanently if the copyright holder notifies you of the
 | 
			
		||||
violation by some reasonable means, this is the first time you have
 | 
			
		||||
received notice of violation of this License (for any work) from that
 | 
			
		||||
copyright holder, and you cure the violation prior to 30 days after
 | 
			
		||||
your receipt of the notice.
 | 
			
		||||
 | 
			
		||||
  Termination of your rights under this section does not terminate the
 | 
			
		||||
licenses of parties who have received copies or rights from you under
 | 
			
		||||
this License.  If your rights have been terminated and not permanently
 | 
			
		||||
reinstated, you do not qualify to receive new licenses for the same
 | 
			
		||||
material under section 10.
 | 
			
		||||
 | 
			
		||||
  9. Acceptance Not Required for Having Copies.
 | 
			
		||||
 | 
			
		||||
  You are not required to accept this License in order to receive or
 | 
			
		||||
run a copy of the Program.  Ancillary propagation of a covered work
 | 
			
		||||
occurring solely as a consequence of using peer-to-peer transmission
 | 
			
		||||
to receive a copy likewise does not require acceptance.  However,
 | 
			
		||||
nothing other than this License grants you permission to propagate or
 | 
			
		||||
modify any covered work.  These actions infringe copyright if you do
 | 
			
		||||
not accept this License.  Therefore, by modifying or propagating a
 | 
			
		||||
covered work, you indicate your acceptance of this License to do so.
 | 
			
		||||
 | 
			
		||||
  10. Automatic Licensing of Downstream Recipients.
 | 
			
		||||
 | 
			
		||||
  Each time you convey a covered work, the recipient automatically
 | 
			
		||||
receives a license from the original licensors, to run, modify and
 | 
			
		||||
propagate that work, subject to this License.  You are not responsible
 | 
			
		||||
for enforcing compliance by third parties with this License.
 | 
			
		||||
 | 
			
		||||
  An "entity transaction" is a transaction transferring control of an
 | 
			
		||||
organization, or substantially all assets of one, or subdividing an
 | 
			
		||||
organization, or merging organizations.  If propagation of a covered
 | 
			
		||||
work results from an entity transaction, each party to that
 | 
			
		||||
transaction who receives a copy of the work also receives whatever
 | 
			
		||||
licenses to the work the party's predecessor in interest had or could
 | 
			
		||||
give under the previous paragraph, plus a right to possession of the
 | 
			
		||||
Corresponding Source of the work from the predecessor in interest, if
 | 
			
		||||
the predecessor has it or can get it with reasonable efforts.
 | 
			
		||||
 | 
			
		||||
  You may not impose any further restrictions on the exercise of the
 | 
			
		||||
rights granted or affirmed under this License.  For example, you may
 | 
			
		||||
not impose a license fee, royalty, or other charge for exercise of
 | 
			
		||||
rights granted under this License, and you may not initiate litigation
 | 
			
		||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
 | 
			
		||||
any patent claim is infringed by making, using, selling, offering for
 | 
			
		||||
sale, or importing the Program or any portion of it.
 | 
			
		||||
 | 
			
		||||
  11. Patents.
 | 
			
		||||
 | 
			
		||||
  A "contributor" is a copyright holder who authorizes use under this
 | 
			
		||||
License of the Program or a work on which the Program is based.  The
 | 
			
		||||
work thus licensed is called the contributor's "contributor version".
 | 
			
		||||
 | 
			
		||||
  A contributor's "essential patent claims" are all patent claims
 | 
			
		||||
owned or controlled by the contributor, whether already acquired or
 | 
			
		||||
hereafter acquired, that would be infringed by some manner, permitted
 | 
			
		||||
by this License, of making, using, or selling its contributor version,
 | 
			
		||||
but do not include claims that would be infringed only as a
 | 
			
		||||
consequence of further modification of the contributor version.  For
 | 
			
		||||
purposes of this definition, "control" includes the right to grant
 | 
			
		||||
patent sublicenses in a manner consistent with the requirements of
 | 
			
		||||
this License.
 | 
			
		||||
 | 
			
		||||
  Each contributor grants you a non-exclusive, worldwide, royalty-free
 | 
			
		||||
patent license under the contributor's essential patent claims, to
 | 
			
		||||
make, use, sell, offer for sale, import and otherwise run, modify and
 | 
			
		||||
propagate the contents of its contributor version.
 | 
			
		||||
 | 
			
		||||
  In the following three paragraphs, a "patent license" is any express
 | 
			
		||||
agreement or commitment, however denominated, not to enforce a patent
 | 
			
		||||
(such as an express permission to practice a patent or covenant not to
 | 
			
		||||
sue for patent infringement).  To "grant" such a patent license to a
 | 
			
		||||
party means to make such an agreement or commitment not to enforce a
 | 
			
		||||
patent against the party.
 | 
			
		||||
 | 
			
		||||
  If you convey a covered work, knowingly relying on a patent license,
 | 
			
		||||
and the Corresponding Source of the work is not available for anyone
 | 
			
		||||
to copy, free of charge and under the terms of this License, through a
 | 
			
		||||
publicly available network server or other readily accessible means,
 | 
			
		||||
then you must either (1) cause the Corresponding Source to be so
 | 
			
		||||
available, or (2) arrange to deprive yourself of the benefit of the
 | 
			
		||||
patent license for this particular work, or (3) arrange, in a manner
 | 
			
		||||
consistent with the requirements of this License, to extend the patent
 | 
			
		||||
license to downstream recipients.  "Knowingly relying" means you have
 | 
			
		||||
actual knowledge that, but for the patent license, your conveying the
 | 
			
		||||
covered work in a country, or your recipient's use of the covered work
 | 
			
		||||
in a country, would infringe one or more identifiable patents in that
 | 
			
		||||
country that you have reason to believe are valid.
 | 
			
		||||
  
 | 
			
		||||
  If, pursuant to or in connection with a single transaction or
 | 
			
		||||
arrangement, you convey, or propagate by procuring conveyance of, a
 | 
			
		||||
covered work, and grant a patent license to some of the parties
 | 
			
		||||
receiving the covered work authorizing them to use, propagate, modify
 | 
			
		||||
or convey a specific copy of the covered work, then the patent license
 | 
			
		||||
you grant is automatically extended to all recipients of the covered
 | 
			
		||||
work and works based on it.
 | 
			
		||||
 | 
			
		||||
  A patent license is "discriminatory" if it does not include within
 | 
			
		||||
the scope of its coverage, prohibits the exercise of, or is
 | 
			
		||||
conditioned on the non-exercise of one or more of the rights that are
 | 
			
		||||
specifically granted under this License.  You may not convey a covered
 | 
			
		||||
work if you are a party to an arrangement with a third party that is
 | 
			
		||||
in the business of distributing software, under which you make payment
 | 
			
		||||
to the third party based on the extent of your activity of conveying
 | 
			
		||||
the work, and under which the third party grants, to any of the
 | 
			
		||||
parties who would receive the covered work from you, a discriminatory
 | 
			
		||||
patent license (a) in connection with copies of the covered work
 | 
			
		||||
conveyed by you (or copies made from those copies), or (b) primarily
 | 
			
		||||
for and in connection with specific products or compilations that
 | 
			
		||||
contain the covered work, unless you entered into that arrangement,
 | 
			
		||||
or that patent license was granted, prior to 28 March 2007.
 | 
			
		||||
 | 
			
		||||
  Nothing in this License shall be construed as excluding or limiting
 | 
			
		||||
any implied license or other defenses to infringement that may
 | 
			
		||||
otherwise be available to you under applicable patent law.
 | 
			
		||||
 | 
			
		||||
  12. No Surrender of Others' Freedom.
 | 
			
		||||
 | 
			
		||||
  If conditions are imposed on you (whether by court order, agreement or
 | 
			
		||||
otherwise) that contradict the conditions of this License, they do not
 | 
			
		||||
excuse you from the conditions of this License.  If you cannot convey a
 | 
			
		||||
covered work so as to satisfy simultaneously your obligations under this
 | 
			
		||||
License and any other pertinent obligations, then as a consequence you may
 | 
			
		||||
not convey it at all.  For example, if you agree to terms that obligate you
 | 
			
		||||
to collect a royalty for further conveying from those to whom you convey
 | 
			
		||||
the Program, the only way you could satisfy both those terms and this
 | 
			
		||||
License would be to refrain entirely from conveying the Program.
 | 
			
		||||
 | 
			
		||||
  13. Use with the GNU Affero General Public License.
 | 
			
		||||
 | 
			
		||||
  Notwithstanding any other provision of this License, you have
 | 
			
		||||
permission to link or combine any covered work with a work licensed
 | 
			
		||||
under version 3 of the GNU Affero General Public License into a single
 | 
			
		||||
combined work, and to convey the resulting work.  The terms of this
 | 
			
		||||
License will continue to apply to the part which is the covered work,
 | 
			
		||||
but the special requirements of the GNU Affero General Public License,
 | 
			
		||||
section 13, concerning interaction through a network will apply to the
 | 
			
		||||
combination as such.
 | 
			
		||||
 | 
			
		||||
  14. Revised Versions of this License.
 | 
			
		||||
 | 
			
		||||
  The Free Software Foundation may publish revised and/or new versions of
 | 
			
		||||
the GNU General Public License from time to time.  Such new versions will
 | 
			
		||||
be similar in spirit to the present version, but may differ in detail to
 | 
			
		||||
address new problems or concerns.
 | 
			
		||||
 | 
			
		||||
  Each version is given a distinguishing version number.  If the
 | 
			
		||||
Program specifies that a certain numbered version of the GNU General
 | 
			
		||||
Public License "or any later version" applies to it, you have the
 | 
			
		||||
option of following the terms and conditions either of that numbered
 | 
			
		||||
version or of any later version published by the Free Software
 | 
			
		||||
Foundation.  If the Program does not specify a version number of the
 | 
			
		||||
GNU General Public License, you may choose any version ever published
 | 
			
		||||
by the Free Software Foundation.
 | 
			
		||||
 | 
			
		||||
  If the Program specifies that a proxy can decide which future
 | 
			
		||||
versions of the GNU General Public License can be used, that proxy's
 | 
			
		||||
public statement of acceptance of a version permanently authorizes you
 | 
			
		||||
to choose that version for the Program.
 | 
			
		||||
 | 
			
		||||
  Later license versions may give you additional or different
 | 
			
		||||
permissions.  However, no additional obligations are imposed on any
 | 
			
		||||
author or copyright holder as a result of your choosing to follow a
 | 
			
		||||
later version.
 | 
			
		||||
 | 
			
		||||
  15. Disclaimer of Warranty.
 | 
			
		||||
 | 
			
		||||
  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 | 
			
		||||
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 | 
			
		||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 | 
			
		||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
			
		||||
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 | 
			
		||||
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 | 
			
		||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 | 
			
		||||
 | 
			
		||||
  16. Limitation of Liability.
 | 
			
		||||
 | 
			
		||||
  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
			
		||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 | 
			
		||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 | 
			
		||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 | 
			
		||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 | 
			
		||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 | 
			
		||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 | 
			
		||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
SUCH DAMAGES.
 | 
			
		||||
 | 
			
		||||
  17. Interpretation of Sections 15 and 16.
 | 
			
		||||
 | 
			
		||||
  If the disclaimer of warranty and limitation of liability provided
 | 
			
		||||
above cannot be given local legal effect according to their terms,
 | 
			
		||||
reviewing courts shall apply local law that most closely approximates
 | 
			
		||||
an absolute waiver of all civil liability in connection with the
 | 
			
		||||
Program, unless a warranty or assumption of liability accompanies a
 | 
			
		||||
copy of the Program in return for a fee.
 | 
			
		||||
 | 
			
		||||
		     END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
	    How to Apply These Terms to Your New Programs
 | 
			
		||||
 | 
			
		||||
  If you develop a new program, and you want it to be of the greatest
 | 
			
		||||
possible use to the public, the best way to achieve this is to make it
 | 
			
		||||
free software which everyone can redistribute and change under these terms.
 | 
			
		||||
 | 
			
		||||
  To do so, attach the following notices to the program.  It is safest
 | 
			
		||||
to attach them to the start of each source file to most effectively
 | 
			
		||||
state the exclusion of warranty; and each file should have at least
 | 
			
		||||
the "copyright" line and a pointer to where the full notice is found.
 | 
			
		||||
 | 
			
		||||
    <one line to give the program's name and a brief idea of what it does.>
 | 
			
		||||
    Copyright (C) <year>  <name of author>
 | 
			
		||||
 | 
			
		||||
    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/>.
 | 
			
		||||
 | 
			
		||||
Also add information on how to contact you by electronic and paper mail.
 | 
			
		||||
 | 
			
		||||
  If the program does terminal interaction, make it output a short
 | 
			
		||||
notice like this when it starts in an interactive mode:
 | 
			
		||||
 | 
			
		||||
    <program>  Copyright (C) <year>  <name of author>
 | 
			
		||||
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
			
		||||
    This is free software, and you are welcome to redistribute it
 | 
			
		||||
    under certain conditions; type `show c' for details.
 | 
			
		||||
 | 
			
		||||
The hypothetical commands `show w' and `show c' should show the appropriate
 | 
			
		||||
parts of the General Public License.  Of course, your program's commands
 | 
			
		||||
might be different; for a GUI interface, you would use an "about box".
 | 
			
		||||
 | 
			
		||||
  You should also get your employer (if you work as a programmer) or school,
 | 
			
		||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
 | 
			
		||||
For more information on this, and how to apply and follow the GNU GPL, see
 | 
			
		||||
<http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
  The GNU General Public License does not permit incorporating your program
 | 
			
		||||
into proprietary programs.  If your program is a subroutine library, you
 | 
			
		||||
may consider it more useful to permit linking proprietary applications with
 | 
			
		||||
the library.  If this is what you want to do, use the GNU Lesser General
 | 
			
		||||
Public License instead of this License.  But first, please read
 | 
			
		||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
 | 
			
		||||
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
This is the file .../info/dir, which contains the
 | 
			
		||||
topmost node of the Info hierarchy, called (dir)Top.
 | 
			
		||||
The first time you invoke Info you start off looking at this node.
 | 
			
		||||
 | 
			
		||||
File: dir,	Node: Top	This is the top of the INFO tree
 | 
			
		||||
 | 
			
		||||
  This (the Directory node) gives a menu of major topics.
 | 
			
		||||
  Typing "q" exits, "H" lists all Info commands, "d" returns here,
 | 
			
		||||
  "h" gives a primer for first-timers,
 | 
			
		||||
  "mEmacs<Return>" visits the Emacs manual, etc.
 | 
			
		||||
 | 
			
		||||
  In Emacs, you can click mouse button 2 on a menu item or cross reference
 | 
			
		||||
  to select it.
 | 
			
		||||
 | 
			
		||||
* Menu:
 | 
			
		||||
 | 
			
		||||
Emacs
 | 
			
		||||
* Magit: (magit).               Using Git from Emacs with Magit.
 | 
			
		||||
@@ -1,804 +0,0 @@
 | 
			
		||||
;;; git-rebase.el --- Edit Git rebase files  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Phil Jackson <phil@shellarchive.co.uk>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; This file is not part of GNU Emacs.
 | 
			
		||||
 | 
			
		||||
;; This file 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
 | 
			
		||||
;; This file 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 file.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This package assists the user in editing the list of commits to be
 | 
			
		||||
;; rewritten during an interactive rebase.
 | 
			
		||||
 | 
			
		||||
;; When the user initiates an interactive rebase, e.g. using "r e" in
 | 
			
		||||
;; a Magit buffer or on the command line using "git rebase -i REV",
 | 
			
		||||
;; Git invokes the `$GIT_SEQUENCE_EDITOR' (or if that is undefined
 | 
			
		||||
;; `$GIT_EDITOR' or even `$EDITOR') letting the user rearrange, drop,
 | 
			
		||||
;; reword, edit, and squash commits.
 | 
			
		||||
 | 
			
		||||
;; This package provides the major-mode `git-rebase-mode' which makes
 | 
			
		||||
;; doing so much more fun, by making the buffer more colorful and
 | 
			
		||||
;; providing the following commands:
 | 
			
		||||
;;
 | 
			
		||||
;;   C-c C-c  Tell Git to make it happen.
 | 
			
		||||
;;   C-c C-k  Tell Git that you changed your mind, i.e. abort.
 | 
			
		||||
;;
 | 
			
		||||
;;   p        Move point to previous line.
 | 
			
		||||
;;   n        Move point to next line.
 | 
			
		||||
;;
 | 
			
		||||
;;   M-p      Move the commit at point up.
 | 
			
		||||
;;   M-n      Move the commit at point down.
 | 
			
		||||
;;
 | 
			
		||||
;;   k        Drop the commit at point.
 | 
			
		||||
;;   c        Don't drop the commit at point.
 | 
			
		||||
;;   r        Change the message of the commit at point.
 | 
			
		||||
;;   e        Edit the commit at point.
 | 
			
		||||
;;   s        Squash the commit at point, into the one above.
 | 
			
		||||
;;   f        Like "s" but don't also edit the commit message.
 | 
			
		||||
;;   b        Break for editing at this point in the sequence.
 | 
			
		||||
;;   x        Add a script to be run with the commit at point
 | 
			
		||||
;;            being checked out.
 | 
			
		||||
;;   z        Add noop action at point.
 | 
			
		||||
;;
 | 
			
		||||
;;   SPC      Show the commit at point in another buffer.
 | 
			
		||||
;;   RET      Show the commit at point in another buffer and
 | 
			
		||||
;;            select its window.
 | 
			
		||||
;;   C-/      Undo last change.
 | 
			
		||||
;;
 | 
			
		||||
;;   Commands for --rebase-merges:
 | 
			
		||||
;;   l        Associate label with current HEAD in sequence.
 | 
			
		||||
;;   MM       Merge specified revisions into HEAD.
 | 
			
		||||
;;   Mt       Toggle whether the merge will invoke an editor
 | 
			
		||||
;;            before committing.
 | 
			
		||||
;;   t        Reset HEAD to the specified label.
 | 
			
		||||
 | 
			
		||||
;; You should probably also read the `git-rebase' manpage.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'dash)
 | 
			
		||||
(require 'easymenu)
 | 
			
		||||
(require 'server)
 | 
			
		||||
(require 'with-editor)
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
(and (require 'async-bytecomp nil t)
 | 
			
		||||
     (let ((pkgs (bound-and-true-p async-bytecomp-allowed-packages)))
 | 
			
		||||
       (if (consp pkgs)
 | 
			
		||||
           (cl-intersection '(all magit) pkgs)
 | 
			
		||||
         (memq pkgs '(all t))))
 | 
			
		||||
     (fboundp 'async-bytecomp-package-mode)
 | 
			
		||||
     (async-bytecomp-package-mode 1))
 | 
			
		||||
 | 
			
		||||
(eval-when-compile (require 'recentf))
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
;;;; Variables
 | 
			
		||||
 | 
			
		||||
(defgroup git-rebase nil
 | 
			
		||||
  "Edit Git rebase sequences."
 | 
			
		||||
  :link '(info-link "(magit)Editing Rebase Sequences")
 | 
			
		||||
  :group 'tools)
 | 
			
		||||
 | 
			
		||||
(defcustom git-rebase-auto-advance t
 | 
			
		||||
  "Whether to move to next line after changing a line."
 | 
			
		||||
  :group 'git-rebase
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom git-rebase-show-instructions t
 | 
			
		||||
  "Whether to show usage instructions inside the rebase buffer."
 | 
			
		||||
  :group 'git-rebase
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom git-rebase-confirm-cancel t
 | 
			
		||||
  "Whether confirmation is required to cancel."
 | 
			
		||||
  :group 'git-rebase
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
;;;; Faces
 | 
			
		||||
 | 
			
		||||
(defgroup git-rebase-faces nil
 | 
			
		||||
  "Faces used by Git-Rebase mode."
 | 
			
		||||
  :group 'faces
 | 
			
		||||
  :group 'git-rebase)
 | 
			
		||||
 | 
			
		||||
(defface git-rebase-hash '((t (:inherit magit-hash)))
 | 
			
		||||
  "Face for commit hashes."
 | 
			
		||||
  :group 'git-rebase-faces)
 | 
			
		||||
 | 
			
		||||
(defface git-rebase-label '((t (:inherit magit-refname)))
 | 
			
		||||
  "Face for labels in label, merge, and reset lines."
 | 
			
		||||
  :group 'git-rebase-faces)
 | 
			
		||||
 | 
			
		||||
(defface git-rebase-description nil
 | 
			
		||||
  "Face for commit descriptions."
 | 
			
		||||
  :group 'git-rebase-faces)
 | 
			
		||||
 | 
			
		||||
(defface git-rebase-killed-action
 | 
			
		||||
  '((t (:inherit font-lock-comment-face :strike-through t)))
 | 
			
		||||
  "Face for commented commit action lines."
 | 
			
		||||
  :group 'git-rebase-faces)
 | 
			
		||||
 | 
			
		||||
(defface git-rebase-comment-hash
 | 
			
		||||
  '((t (:inherit git-rebase-hash :weight bold)))
 | 
			
		||||
  "Face for commit hashes in commit message comments."
 | 
			
		||||
  :group 'git-rebase-faces)
 | 
			
		||||
 | 
			
		||||
(defface git-rebase-comment-heading
 | 
			
		||||
  '((t :inherit font-lock-keyword-face))
 | 
			
		||||
  "Face for headings in rebase message comments."
 | 
			
		||||
  :group 'git-commit-faces)
 | 
			
		||||
 | 
			
		||||
;;; Keymaps
 | 
			
		||||
 | 
			
		||||
(defvar git-rebase-mode-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (set-keymap-parent map special-mode-map)
 | 
			
		||||
    (define-key map (kbd "C-m") 'git-rebase-show-commit)
 | 
			
		||||
    (define-key map (kbd   "p") 'git-rebase-backward-line)
 | 
			
		||||
    (define-key map (kbd   "n") 'forward-line)
 | 
			
		||||
    (define-key map (kbd "M-p") 'git-rebase-move-line-up)
 | 
			
		||||
    (define-key map (kbd "M-n") 'git-rebase-move-line-down)
 | 
			
		||||
    (define-key map (kbd   "c") 'git-rebase-pick)
 | 
			
		||||
    (define-key map (kbd   "k") 'git-rebase-kill-line)
 | 
			
		||||
    (define-key map (kbd "C-k") 'git-rebase-kill-line)
 | 
			
		||||
    (define-key map (kbd "b") 'git-rebase-break)
 | 
			
		||||
    (define-key map (kbd "e") 'git-rebase-edit)
 | 
			
		||||
    (define-key map (kbd "l") 'git-rebase-label)
 | 
			
		||||
    (define-key map (kbd "MM") 'git-rebase-merge)
 | 
			
		||||
    (define-key map (kbd "Mt") 'git-rebase-merge-toggle-editmsg)
 | 
			
		||||
    (define-key map (kbd "m") 'git-rebase-edit)
 | 
			
		||||
    (define-key map (kbd "f") 'git-rebase-fixup)
 | 
			
		||||
    (define-key map (kbd "q") 'undefined)
 | 
			
		||||
    (define-key map (kbd "r") 'git-rebase-reword)
 | 
			
		||||
    (define-key map (kbd "w") 'git-rebase-reword)
 | 
			
		||||
    (define-key map (kbd "s") 'git-rebase-squash)
 | 
			
		||||
    (define-key map (kbd "t") 'git-rebase-reset)
 | 
			
		||||
    (define-key map (kbd "x") 'git-rebase-exec)
 | 
			
		||||
    (define-key map (kbd "y") 'git-rebase-insert)
 | 
			
		||||
    (define-key map (kbd "z") 'git-rebase-noop)
 | 
			
		||||
    (define-key map (kbd "SPC")     'git-rebase-show-or-scroll-up)
 | 
			
		||||
    (define-key map (kbd "DEL")     'git-rebase-show-or-scroll-down)
 | 
			
		||||
    (define-key map (kbd "C-x C-t") 'git-rebase-move-line-up)
 | 
			
		||||
    (define-key map [M-up]          'git-rebase-move-line-up)
 | 
			
		||||
    (define-key map [M-down]        'git-rebase-move-line-down)
 | 
			
		||||
    (define-key map [remap undo]    'git-rebase-undo)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for Git-Rebase mode.")
 | 
			
		||||
 | 
			
		||||
(put 'git-rebase-reword       :advertised-binding (kbd "r"))
 | 
			
		||||
(put 'git-rebase-move-line-up :advertised-binding (kbd "M-p"))
 | 
			
		||||
(put 'git-rebase-kill-line    :advertised-binding (kbd "k"))
 | 
			
		||||
 | 
			
		||||
(easy-menu-define git-rebase-mode-menu git-rebase-mode-map
 | 
			
		||||
  "Git-Rebase mode menu"
 | 
			
		||||
  '("Rebase"
 | 
			
		||||
    ["Pick" git-rebase-pick t]
 | 
			
		||||
    ["Reword" git-rebase-reword t]
 | 
			
		||||
    ["Edit" git-rebase-edit t]
 | 
			
		||||
    ["Squash" git-rebase-squash t]
 | 
			
		||||
    ["Fixup" git-rebase-fixup t]
 | 
			
		||||
    ["Kill" git-rebase-kill-line t]
 | 
			
		||||
    ["Noop" git-rebase-noop t]
 | 
			
		||||
    ["Execute" git-rebase-exec t]
 | 
			
		||||
    ["Move Down" git-rebase-move-line-down t]
 | 
			
		||||
    ["Move Up" git-rebase-move-line-up t]
 | 
			
		||||
    "---"
 | 
			
		||||
    ["Cancel" with-editor-cancel t]
 | 
			
		||||
    ["Finish" with-editor-finish t]))
 | 
			
		||||
 | 
			
		||||
(defvar git-rebase-command-descriptions
 | 
			
		||||
  '((with-editor-finish           . "tell Git to make it happen")
 | 
			
		||||
    (with-editor-cancel           . "tell Git that you changed your mind, i.e. abort")
 | 
			
		||||
    (git-rebase-backward-line     . "move point to previous line")
 | 
			
		||||
    (forward-line                 . "move point to next line")
 | 
			
		||||
    (git-rebase-move-line-up      . "move the commit at point up")
 | 
			
		||||
    (git-rebase-move-line-down    . "move the commit at point down")
 | 
			
		||||
    (git-rebase-show-or-scroll-up . "show the commit at point in another buffer")
 | 
			
		||||
    (git-rebase-show-commit
 | 
			
		||||
     . "show the commit at point in another buffer and select its window")
 | 
			
		||||
    (undo                         . "undo last change")
 | 
			
		||||
    (git-rebase-kill-line         . "drop the commit at point")
 | 
			
		||||
    (git-rebase-insert            . "insert a line for an arbitrary commit")
 | 
			
		||||
    (git-rebase-noop              . "add noop action at point")))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-pick ()
 | 
			
		||||
  "Use commit on current line."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase-set-action "pick"))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-reword ()
 | 
			
		||||
  "Edit message of commit on current line."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase-set-action "reword"))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-edit ()
 | 
			
		||||
  "Stop at the commit on the current line."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase-set-action "edit"))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-squash ()
 | 
			
		||||
  "Meld commit on current line into previous commit, edit message."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase-set-action "squash"))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-fixup ()
 | 
			
		||||
  "Meld commit on current line into previous commit, discard its message."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase-set-action "fixup"))
 | 
			
		||||
 | 
			
		||||
(defvar-local git-rebase-comment-re nil)
 | 
			
		||||
 | 
			
		||||
(defvar git-rebase-short-options
 | 
			
		||||
  '((?b . "break")
 | 
			
		||||
    (?e . "edit")
 | 
			
		||||
    (?f . "fixup")
 | 
			
		||||
    (?l . "label")
 | 
			
		||||
    (?m . "merge")
 | 
			
		||||
    (?p . "pick")
 | 
			
		||||
    (?r . "reword")
 | 
			
		||||
    (?s . "squash")
 | 
			
		||||
    (?t . "reset")
 | 
			
		||||
    (?x . "exec"))
 | 
			
		||||
  "Alist mapping single key of an action to the full name.")
 | 
			
		||||
 | 
			
		||||
(defclass git-rebase-action ()
 | 
			
		||||
  (;; action-type: commit, exec, bare, label, merge
 | 
			
		||||
   (action-type    :initarg :action-type    :initform nil)
 | 
			
		||||
   ;; Examples for each action type:
 | 
			
		||||
   ;; | action | action options | target  | trailer |
 | 
			
		||||
   ;; |--------+----------------+---------+---------|
 | 
			
		||||
   ;; | pick   |                | hash    | subject |
 | 
			
		||||
   ;; | exec   |                | command |         |
 | 
			
		||||
   ;; | noop   |                |         |         |
 | 
			
		||||
   ;; | reset  |                | name    | subject |
 | 
			
		||||
   ;; | merge  | -C hash        | name    | subject |
 | 
			
		||||
   (action         :initarg :action         :initform nil)
 | 
			
		||||
   (action-options :initarg :action-options :initform nil)
 | 
			
		||||
   (target         :initarg :target         :initform nil)
 | 
			
		||||
   (trailer        :initarg :trailer        :initform nil)
 | 
			
		||||
   (comment-p      :initarg :comment-p      :initform nil)))
 | 
			
		||||
 | 
			
		||||
(defvar git-rebase-line-regexps
 | 
			
		||||
  `((commit . ,(concat
 | 
			
		||||
                (regexp-opt '("e" "edit"
 | 
			
		||||
                              "f" "fixup"
 | 
			
		||||
                              "p" "pick"
 | 
			
		||||
                              "r" "reword"
 | 
			
		||||
                              "s" "squash")
 | 
			
		||||
                            "\\(?1:")
 | 
			
		||||
                " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)"))
 | 
			
		||||
    (exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)")
 | 
			
		||||
    (bare . ,(concat (regexp-opt '("b" "break" "noop") "\\(?1:")
 | 
			
		||||
                     " *$"))
 | 
			
		||||
    (label . ,(concat (regexp-opt '("l" "label"
 | 
			
		||||
                                    "t" "reset")
 | 
			
		||||
                                  "\\(?1:")
 | 
			
		||||
                      " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)"))
 | 
			
		||||
    (merge . ,(concat "\\(?1:m\\|merge\\) "
 | 
			
		||||
                      "\\(?:\\(?2:-[cC] [^ \n]+\\) \\)?"
 | 
			
		||||
                      "\\(?3:[^ \n]+\\)"
 | 
			
		||||
                      " ?\\(?4:.*\\)"))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun git-rebase-current-line ()
 | 
			
		||||
  "Parse current line into a `git-rebase-action' instance.
 | 
			
		||||
If the current line isn't recognized as a rebase line, an
 | 
			
		||||
instance with all nil values is returned."
 | 
			
		||||
  (save-excursion
 | 
			
		||||
    (goto-char (line-beginning-position))
 | 
			
		||||
    (if-let ((re-start (concat "^\\(?5:" (regexp-quote comment-start)
 | 
			
		||||
                               "\\)? *"))
 | 
			
		||||
             (type (-some (lambda (arg)
 | 
			
		||||
                            (let ((case-fold-search nil))
 | 
			
		||||
                              (and (looking-at (concat re-start (cdr arg)))
 | 
			
		||||
                                   (car arg))))
 | 
			
		||||
                          git-rebase-line-regexps)))
 | 
			
		||||
        (git-rebase-action
 | 
			
		||||
         :action-type    type
 | 
			
		||||
         :action         (when-let ((action (match-string-no-properties 1)))
 | 
			
		||||
                           (or (cdr (assoc action git-rebase-short-options))
 | 
			
		||||
                               action))
 | 
			
		||||
         :action-options (match-string-no-properties 2)
 | 
			
		||||
         :target         (match-string-no-properties 3)
 | 
			
		||||
         :trailer        (match-string-no-properties 4)
 | 
			
		||||
         :comment-p      (and (match-string 5) t))
 | 
			
		||||
      ;; Use default empty class rather than nil to ease handling.
 | 
			
		||||
      (git-rebase-action))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-set-action (action)
 | 
			
		||||
  (goto-char (line-beginning-position))
 | 
			
		||||
  (with-slots (action-type target trailer)
 | 
			
		||||
      (git-rebase-current-line)
 | 
			
		||||
    (if (eq action-type 'commit)
 | 
			
		||||
        (let ((inhibit-read-only t))
 | 
			
		||||
          (magit-delete-line)
 | 
			
		||||
          (insert (concat action " " target " " trailer "\n"))
 | 
			
		||||
          (unless git-rebase-auto-advance
 | 
			
		||||
            (forward-line -1)))
 | 
			
		||||
      (ding))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-line-p (&optional pos)
 | 
			
		||||
  (save-excursion
 | 
			
		||||
    (when pos (goto-char pos))
 | 
			
		||||
    (and (oref (git-rebase-current-line) action-type)
 | 
			
		||||
         t)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-region-bounds ()
 | 
			
		||||
  (when (use-region-p)
 | 
			
		||||
    (let ((beg (save-excursion (goto-char (region-beginning))
 | 
			
		||||
                               (line-beginning-position)))
 | 
			
		||||
          (end (save-excursion (goto-char (region-end))
 | 
			
		||||
                               (line-end-position))))
 | 
			
		||||
      (when (and (git-rebase-line-p beg)
 | 
			
		||||
                 (git-rebase-line-p end))
 | 
			
		||||
        (list beg (1+ end))))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-move-line-down (n)
 | 
			
		||||
  "Move the current commit (or command) N lines down.
 | 
			
		||||
If N is negative, move the commit up instead.  With an active
 | 
			
		||||
region, move all the lines that the region touches, not just the
 | 
			
		||||
current line."
 | 
			
		||||
  (interactive "p")
 | 
			
		||||
  (pcase-let* ((`(,beg ,end)
 | 
			
		||||
                (or (git-rebase-region-bounds)
 | 
			
		||||
                    (list (line-beginning-position)
 | 
			
		||||
                          (1+ (line-end-position)))))
 | 
			
		||||
               (pt-offset (- (point) beg))
 | 
			
		||||
               (mark-offset (and mark-active (- (mark) beg))))
 | 
			
		||||
    (save-restriction
 | 
			
		||||
      (narrow-to-region
 | 
			
		||||
       (point-min)
 | 
			
		||||
       (1-
 | 
			
		||||
        (if git-rebase-show-instructions
 | 
			
		||||
            (save-excursion
 | 
			
		||||
              (goto-char (point-min))
 | 
			
		||||
              (while (or (git-rebase-line-p)
 | 
			
		||||
                         ;; The output for --rebase-merges has empty
 | 
			
		||||
                         ;; lines and "Branch" comments interspersed.
 | 
			
		||||
                         (looking-at-p "^$")
 | 
			
		||||
                         (looking-at-p (concat git-rebase-comment-re
 | 
			
		||||
                                               " Branch")))
 | 
			
		||||
                (forward-line))
 | 
			
		||||
              (line-beginning-position))
 | 
			
		||||
          (point-max))))
 | 
			
		||||
      (if (or (and (< n 0) (= beg (point-min)))
 | 
			
		||||
              (and (> n 0) (= end (point-max)))
 | 
			
		||||
              (> end (point-max)))
 | 
			
		||||
          (ding)
 | 
			
		||||
        (goto-char (if (< n 0) beg end))
 | 
			
		||||
        (forward-line n)
 | 
			
		||||
        (atomic-change-group
 | 
			
		||||
          (let ((inhibit-read-only t))
 | 
			
		||||
            (insert (delete-and-extract-region beg end)))
 | 
			
		||||
          (let ((new-beg (- (point) (- end beg))))
 | 
			
		||||
            (when (use-region-p)
 | 
			
		||||
              (setq deactivate-mark nil)
 | 
			
		||||
              (set-mark (+ new-beg mark-offset)))
 | 
			
		||||
            (goto-char (+ new-beg pt-offset))))))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-move-line-up (n)
 | 
			
		||||
  "Move the current commit (or command) N lines up.
 | 
			
		||||
If N is negative, move the commit down instead.  With an active
 | 
			
		||||
region, move all the lines that the region touches, not just the
 | 
			
		||||
current line."
 | 
			
		||||
  (interactive "p")
 | 
			
		||||
  (git-rebase-move-line-down (- n)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-highlight-region (start end window rol)
 | 
			
		||||
  (let ((inhibit-read-only t)
 | 
			
		||||
        (deactivate-mark nil)
 | 
			
		||||
        (bounds (git-rebase-region-bounds)))
 | 
			
		||||
    (mapc #'delete-overlay magit-section-highlight-overlays)
 | 
			
		||||
    (when bounds
 | 
			
		||||
      (magit-section-make-overlay (car bounds) (cadr bounds)
 | 
			
		||||
                                  'magit-section-heading-selection))
 | 
			
		||||
    (if (and bounds (not magit-keep-region-overlay))
 | 
			
		||||
        (funcall (default-value 'redisplay-unhighlight-region-function) rol)
 | 
			
		||||
      (funcall (default-value 'redisplay-highlight-region-function)
 | 
			
		||||
               start end window rol))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-unhighlight-region (rol)
 | 
			
		||||
  (mapc #'delete-overlay magit-section-highlight-overlays)
 | 
			
		||||
  (funcall (default-value 'redisplay-unhighlight-region-function) rol))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-kill-line ()
 | 
			
		||||
  "Kill the current action line."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (goto-char (line-beginning-position))
 | 
			
		||||
  (unless (oref (git-rebase-current-line) comment-p)
 | 
			
		||||
    (let ((inhibit-read-only t))
 | 
			
		||||
      (insert comment-start)
 | 
			
		||||
      (insert " "))
 | 
			
		||||
    (goto-char (line-beginning-position))
 | 
			
		||||
    (when git-rebase-auto-advance
 | 
			
		||||
      (forward-line))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-insert (rev)
 | 
			
		||||
  "Read an arbitrary commit and insert it below current line."
 | 
			
		||||
  (interactive (list (magit-read-branch-or-commit "Insert revision")))
 | 
			
		||||
  (forward-line)
 | 
			
		||||
  (--if-let (magit-rev-format "%h %s" rev)
 | 
			
		||||
      (let ((inhibit-read-only t))
 | 
			
		||||
        (insert "pick " it ?\n))
 | 
			
		||||
    (user-error "Unknown revision")))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-set-noncommit-action (action value-fn arg)
 | 
			
		||||
  (goto-char (line-beginning-position))
 | 
			
		||||
  (pcase-let* ((inhibit-read-only t)
 | 
			
		||||
               (`(,initial ,trailer ,comment-p)
 | 
			
		||||
                (and (not arg)
 | 
			
		||||
                     (with-slots ((ln-action action)
 | 
			
		||||
                                  target trailer comment-p)
 | 
			
		||||
                         (git-rebase-current-line)
 | 
			
		||||
                       (and (equal ln-action action)
 | 
			
		||||
                            (list target trailer comment-p)))))
 | 
			
		||||
               (value (funcall value-fn initial)))
 | 
			
		||||
    (pcase (list value initial comment-p)
 | 
			
		||||
      (`("" nil ,_)
 | 
			
		||||
       (ding))
 | 
			
		||||
      (`(""  ,_ ,_)
 | 
			
		||||
       (magit-delete-line))
 | 
			
		||||
      (_
 | 
			
		||||
       (if initial
 | 
			
		||||
           (magit-delete-line)
 | 
			
		||||
         (forward-line))
 | 
			
		||||
       (insert (concat action " " value
 | 
			
		||||
                       (and (equal value initial)
 | 
			
		||||
                            trailer
 | 
			
		||||
                            (concat " " trailer))
 | 
			
		||||
                       "\n"))
 | 
			
		||||
       (unless git-rebase-auto-advance
 | 
			
		||||
         (forward-line -1))))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-exec (arg)
 | 
			
		||||
  "Insert a shell command to be run after the current commit.
 | 
			
		||||
 | 
			
		||||
If there already is such a command on the current line, then edit
 | 
			
		||||
that instead.  With a prefix argument insert a new command even
 | 
			
		||||
when there already is one on the current line.  With empty input
 | 
			
		||||
remove the command on the current line, if any."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (git-rebase-set-noncommit-action
 | 
			
		||||
   "exec"
 | 
			
		||||
   (lambda (initial) (read-shell-command "Execute: " initial))
 | 
			
		||||
   arg))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-label (arg)
 | 
			
		||||
  "Add a label after the current commit.
 | 
			
		||||
If there already is a label on the current line, then edit that
 | 
			
		||||
instead.  With a prefix argument, insert a new label even when
 | 
			
		||||
there is already a label on the current line.  With empty input,
 | 
			
		||||
remove the label on the current line, if any."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (git-rebase-set-noncommit-action
 | 
			
		||||
   "label"
 | 
			
		||||
   (lambda (initial)
 | 
			
		||||
     (read-from-minibuffer
 | 
			
		||||
      "Label: " initial magit-minibuffer-local-ns-map))
 | 
			
		||||
   arg))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-buffer-labels ()
 | 
			
		||||
  (let (labels)
 | 
			
		||||
    (save-excursion
 | 
			
		||||
      (goto-char (point-min))
 | 
			
		||||
      (while (re-search-forward "^\\(?:l\\|label\\) \\([^ \n]+\\)" nil t)
 | 
			
		||||
        (push (match-string-no-properties 1) labels)))
 | 
			
		||||
    (nreverse labels)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-reset (arg)
 | 
			
		||||
  "Reset the current HEAD to a label.
 | 
			
		||||
If there already is a reset command on the current line, then
 | 
			
		||||
edit that instead.  With a prefix argument, insert a new reset
 | 
			
		||||
line even when point is already on a reset line.  With empty
 | 
			
		||||
input, remove the reset command on the current line, if any."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (git-rebase-set-noncommit-action
 | 
			
		||||
   "reset"
 | 
			
		||||
   (lambda (initial)
 | 
			
		||||
     (or (magit-completing-read "Label" (git-rebase-buffer-labels)
 | 
			
		||||
                                nil t initial)
 | 
			
		||||
         ""))
 | 
			
		||||
   arg))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-merge (arg)
 | 
			
		||||
  "Add a merge command after the current commit.
 | 
			
		||||
If there is already a merge command on the current line, then
 | 
			
		||||
replace that command instead.  With a prefix argument, insert a
 | 
			
		||||
new merge command even when there is already one on the current
 | 
			
		||||
line.  With empty input, remove the merge command on the current
 | 
			
		||||
line, if any."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (git-rebase-set-noncommit-action
 | 
			
		||||
   "merge"
 | 
			
		||||
   (lambda (_)
 | 
			
		||||
     (or (magit-completing-read "Merge" (git-rebase-buffer-labels))
 | 
			
		||||
         ""))
 | 
			
		||||
   arg))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-merge-toggle-editmsg ()
 | 
			
		||||
  "Toggle whether an editor is invoked when performing the merge at point.
 | 
			
		||||
When a merge command uses a lower-case -c, the message for the
 | 
			
		||||
specified commit will be opened in an editor before creating the
 | 
			
		||||
commit.  For an upper-case -C, the message will be used as is."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (with-slots (action-type target action-options trailer)
 | 
			
		||||
      (git-rebase-current-line)
 | 
			
		||||
    (if (eq action-type 'merge)
 | 
			
		||||
        (let ((inhibit-read-only t))
 | 
			
		||||
          (magit-delete-line)
 | 
			
		||||
          (insert
 | 
			
		||||
           (format "merge %s %s %s\n"
 | 
			
		||||
                   (replace-regexp-in-string
 | 
			
		||||
                    "-[cC]" (lambda (c)
 | 
			
		||||
                              (if (equal c "-c") "-C" "-c"))
 | 
			
		||||
                    action-options t t)
 | 
			
		||||
                   target
 | 
			
		||||
                   trailer)))
 | 
			
		||||
      (ding))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-set-bare-action (action arg)
 | 
			
		||||
  (goto-char (line-beginning-position))
 | 
			
		||||
  (with-slots ((ln-action action) comment-p)
 | 
			
		||||
      (git-rebase-current-line)
 | 
			
		||||
    (let ((same-action-p (equal action ln-action))
 | 
			
		||||
          (inhibit-read-only t))
 | 
			
		||||
      (when (or arg
 | 
			
		||||
                (not ln-action)
 | 
			
		||||
                (not same-action-p)
 | 
			
		||||
                (and same-action-p comment-p))
 | 
			
		||||
        (unless (or arg (not same-action-p))
 | 
			
		||||
          (magit-delete-line))
 | 
			
		||||
        (insert action ?\n)
 | 
			
		||||
        (unless git-rebase-auto-advance
 | 
			
		||||
          (forward-line -1))))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-noop (&optional arg)
 | 
			
		||||
  "Add noop action at point.
 | 
			
		||||
 | 
			
		||||
If the current line already contains a noop action, leave it
 | 
			
		||||
unchanged.  If there is a commented noop action present, remove
 | 
			
		||||
the comment.  Otherwise add a new noop action.  With a prefix
 | 
			
		||||
argument insert a new noop action regardless of what is already
 | 
			
		||||
present on the current line.
 | 
			
		||||
 | 
			
		||||
A noop action can be used to make git perform a rebase even if
 | 
			
		||||
no commits are selected.  Without the noop action present, git
 | 
			
		||||
would see an empty file and therefore do nothing."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (git-rebase-set-bare-action "noop" arg))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-break (&optional arg)
 | 
			
		||||
  "Add break action at point.
 | 
			
		||||
 | 
			
		||||
If there is a commented break action present, remove the comment.
 | 
			
		||||
If the current line already contains a break action, add another
 | 
			
		||||
break action only if a prefix argument is given.
 | 
			
		||||
 | 
			
		||||
A break action can be used to interrupt the rebase at the
 | 
			
		||||
specified point.  It is particularly useful for pausing before
 | 
			
		||||
the first commit in the sequence.  For other cases, the
 | 
			
		||||
equivalent behavior can be achieved with `git-rebase-edit'."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (git-rebase-set-bare-action "break" arg))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-undo (&optional arg)
 | 
			
		||||
  "Undo some previous changes.
 | 
			
		||||
Like `undo' but works in read-only buffers."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (let ((inhibit-read-only t))
 | 
			
		||||
    (undo arg)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase--show-commit (&optional scroll)
 | 
			
		||||
  (let ((disable-magit-save-buffers t))
 | 
			
		||||
    (save-excursion
 | 
			
		||||
      (goto-char (line-beginning-position))
 | 
			
		||||
      (--if-let (with-slots (action-type target) (git-rebase-current-line)
 | 
			
		||||
                  (and (eq action-type 'commit)
 | 
			
		||||
                       target))
 | 
			
		||||
          (pcase scroll
 | 
			
		||||
            (`up   (magit-diff-show-or-scroll-up))
 | 
			
		||||
            (`down (magit-diff-show-or-scroll-down))
 | 
			
		||||
            (_     (apply #'magit-show-commit it
 | 
			
		||||
                          (magit-diff-arguments 'magit-revision-mode))))
 | 
			
		||||
        (ding)))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-show-commit ()
 | 
			
		||||
  "Show the commit on the current line if any."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase--show-commit))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-show-or-scroll-up ()
 | 
			
		||||
  "Update the commit buffer for commit on current line.
 | 
			
		||||
 | 
			
		||||
Either show the commit at point in the appropriate buffer, or if
 | 
			
		||||
that buffer is already being displayed in the current frame and
 | 
			
		||||
contains information about that commit, then instead scroll the
 | 
			
		||||
buffer up."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase--show-commit 'up))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-show-or-scroll-down ()
 | 
			
		||||
  "Update the commit buffer for commit on current line.
 | 
			
		||||
 | 
			
		||||
Either show the commit at point in the appropriate buffer, or if
 | 
			
		||||
that buffer is already being displayed in the current frame and
 | 
			
		||||
contains information about that commit, then instead scroll the
 | 
			
		||||
buffer down."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (git-rebase--show-commit 'down))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-backward-line (&optional n)
 | 
			
		||||
  "Move N lines backward (forward if N is negative).
 | 
			
		||||
Like `forward-line' but go into the opposite direction."
 | 
			
		||||
  (interactive "p")
 | 
			
		||||
  (forward-line (- (or n 1))))
 | 
			
		||||
 | 
			
		||||
;;; Mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(define-derived-mode git-rebase-mode special-mode "Git Rebase"
 | 
			
		||||
  "Major mode for editing of a Git rebase file.
 | 
			
		||||
 | 
			
		||||
Rebase files are generated when you run 'git rebase -i' or run
 | 
			
		||||
`magit-interactive-rebase'.  They describe how Git should perform
 | 
			
		||||
the rebase.  See the documentation for git-rebase (e.g., by
 | 
			
		||||
running 'man git-rebase' at the command line) for details."
 | 
			
		||||
  :group 'git-rebase
 | 
			
		||||
  (setq comment-start (or (magit-get "core.commentChar") "#"))
 | 
			
		||||
  (setq git-rebase-comment-re (concat "^" (regexp-quote comment-start)))
 | 
			
		||||
  (setq font-lock-defaults (list (git-rebase-mode-font-lock-keywords) t t))
 | 
			
		||||
  (unless git-rebase-show-instructions
 | 
			
		||||
    (let ((inhibit-read-only t))
 | 
			
		||||
      (flush-lines git-rebase-comment-re)))
 | 
			
		||||
  (unless with-editor-mode
 | 
			
		||||
    ;; Maybe already enabled when using `shell-command' or an Emacs shell.
 | 
			
		||||
    (with-editor-mode 1))
 | 
			
		||||
  (when git-rebase-confirm-cancel
 | 
			
		||||
    (add-hook 'with-editor-cancel-query-functions
 | 
			
		||||
              'git-rebase-cancel-confirm nil t))
 | 
			
		||||
  (setq-local redisplay-highlight-region-function 'git-rebase-highlight-region)
 | 
			
		||||
  (setq-local redisplay-unhighlight-region-function 'git-rebase-unhighlight-region)
 | 
			
		||||
  (add-hook 'with-editor-pre-cancel-hook  'git-rebase-autostash-save  nil t)
 | 
			
		||||
  (add-hook 'with-editor-post-cancel-hook 'git-rebase-autostash-apply nil t)
 | 
			
		||||
  (setq imenu-prev-index-position-function
 | 
			
		||||
        #'magit-imenu--rebase-prev-index-position-function)
 | 
			
		||||
  (setq imenu-extract-index-name-function
 | 
			
		||||
        #'magit-imenu--rebase-extract-index-name-function)
 | 
			
		||||
  (when (boundp 'save-place)
 | 
			
		||||
    (setq save-place nil)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-cancel-confirm (force)
 | 
			
		||||
  (or (not (buffer-modified-p))
 | 
			
		||||
      force
 | 
			
		||||
      (magit-confirm 'abort-rebase "Abort this rebase" nil 'noabort)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-autostash-save ()
 | 
			
		||||
  (--when-let (magit-file-line (magit-git-dir "rebase-merge/autostash"))
 | 
			
		||||
    (push (cons 'stash it) with-editor-cancel-alist)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-autostash-apply ()
 | 
			
		||||
  (--when-let (cdr (assq 'stash with-editor-cancel-alist))
 | 
			
		||||
    (magit-stash-apply it)))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-match-comment-line (limit)
 | 
			
		||||
  (re-search-forward (concat git-rebase-comment-re ".*") limit t))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-mode-font-lock-keywords ()
 | 
			
		||||
  "Font lock keywords for Git-Rebase mode."
 | 
			
		||||
  `((,(concat "^" (cdr (assq 'commit git-rebase-line-regexps)))
 | 
			
		||||
     (1 'font-lock-keyword-face)
 | 
			
		||||
     (3 'git-rebase-hash)
 | 
			
		||||
     (4 'git-rebase-description))
 | 
			
		||||
    (,(concat "^" (cdr (assq 'exec git-rebase-line-regexps)))
 | 
			
		||||
     (1 'font-lock-keyword-face)
 | 
			
		||||
     (3 'git-rebase-description))
 | 
			
		||||
    (,(concat "^" (cdr (assq 'bare git-rebase-line-regexps)))
 | 
			
		||||
     (1 'font-lock-keyword-face))
 | 
			
		||||
    (,(concat "^" (cdr (assq 'label git-rebase-line-regexps)))
 | 
			
		||||
     (1 'font-lock-keyword-face)
 | 
			
		||||
     (3 'git-rebase-label)
 | 
			
		||||
     (4 'font-lock-comment-face))
 | 
			
		||||
    ("^\\(m\\(?:erge\\)?\\) -[Cc] \\([^ \n]+\\) \\([^ \n]+\\)\\( #.*\\)?"
 | 
			
		||||
     (1 'font-lock-keyword-face)
 | 
			
		||||
     (2 'git-rebase-hash)
 | 
			
		||||
     (3 'git-rebase-label)
 | 
			
		||||
     (4 'font-lock-comment-face))
 | 
			
		||||
    ("^\\(m\\(?:erge\\)?\\) \\([^ \n]+\\)"
 | 
			
		||||
     (1 'font-lock-keyword-face)
 | 
			
		||||
     (2 'git-rebase-label))
 | 
			
		||||
    (,(concat git-rebase-comment-re " *"
 | 
			
		||||
              (cdr (assq 'commit git-rebase-line-regexps)))
 | 
			
		||||
     0 'git-rebase-killed-action t)
 | 
			
		||||
    (git-rebase-match-comment-line 0 'font-lock-comment-face)
 | 
			
		||||
    ("\\[[^[]*\\]"
 | 
			
		||||
     0 'magit-keyword t)
 | 
			
		||||
    ("\\(?:fixup!\\|squash!\\)"
 | 
			
		||||
     0 'magit-keyword-squash t)
 | 
			
		||||
    (,(format "^%s Rebase \\([^ ]*\\) onto \\([^ ]*\\)" comment-start)
 | 
			
		||||
     (1 'git-rebase-comment-hash t)
 | 
			
		||||
     (2 'git-rebase-comment-hash t))
 | 
			
		||||
    (,(format "^%s \\(Commands:\\)" comment-start)
 | 
			
		||||
     (1 'git-rebase-comment-heading t))
 | 
			
		||||
    (,(format "^%s Branch \\(.*\\)" comment-start)
 | 
			
		||||
     (1 'git-rebase-label t))))
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-mode-show-keybindings ()
 | 
			
		||||
  "Modify the \"Commands:\" section of the comment Git generates
 | 
			
		||||
at the bottom of the file so that in place of the one-letter
 | 
			
		||||
abbreviation for the command, it shows the command's keybinding.
 | 
			
		||||
By default, this is the same except for the \"pick\" command."
 | 
			
		||||
  (let ((inhibit-read-only t))
 | 
			
		||||
    (save-excursion
 | 
			
		||||
      (goto-char (point-min))
 | 
			
		||||
      (when (and git-rebase-show-instructions
 | 
			
		||||
                 (re-search-forward
 | 
			
		||||
                  (concat git-rebase-comment-re "\\s-+p, pick")
 | 
			
		||||
                  nil t))
 | 
			
		||||
        (goto-char (line-beginning-position))
 | 
			
		||||
        (pcase-dolist (`(,cmd . ,desc) git-rebase-command-descriptions)
 | 
			
		||||
          (insert (format "%s %-8s %s\n"
 | 
			
		||||
                          comment-start
 | 
			
		||||
                          (substitute-command-keys (format "\\[%s]" cmd))
 | 
			
		||||
                          desc)))
 | 
			
		||||
        (while (re-search-forward (concat git-rebase-comment-re
 | 
			
		||||
                                          "\\(  ?\\)\\([^\n,],\\) "
 | 
			
		||||
                                          "\\([^\n ]+\\) ")
 | 
			
		||||
                                  nil t)
 | 
			
		||||
          (let ((cmd (intern (concat "git-rebase-" (match-string 3)))))
 | 
			
		||||
            (if (not (fboundp cmd))
 | 
			
		||||
                (delete-region (line-beginning-position) (1+ (line-end-position)))
 | 
			
		||||
              (replace-match " " t t nil 1)
 | 
			
		||||
              (replace-match
 | 
			
		||||
               (format "%-8s"
 | 
			
		||||
                       (mapconcat #'key-description
 | 
			
		||||
                                  (--remove (eq (elt it 0) 'menu-bar)
 | 
			
		||||
                                            (reverse (where-is-internal
 | 
			
		||||
                                                      cmd git-rebase-mode-map)))
 | 
			
		||||
                                  ", "))
 | 
			
		||||
               t t nil 2))))))))
 | 
			
		||||
 | 
			
		||||
(add-hook 'git-rebase-mode-hook 'git-rebase-mode-show-keybindings t)
 | 
			
		||||
 | 
			
		||||
(defun git-rebase-mode-disable-before-save-hook ()
 | 
			
		||||
  (set (make-local-variable 'before-save-hook) nil))
 | 
			
		||||
 | 
			
		||||
(add-hook 'git-rebase-mode-hook 'git-rebase-mode-disable-before-save-hook)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defconst git-rebase-filename-regexp "/git-rebase-todo\\'")
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(add-to-list 'auto-mode-alist
 | 
			
		||||
             (cons git-rebase-filename-regexp 'git-rebase-mode))
 | 
			
		||||
 | 
			
		||||
(add-to-list 'with-editor-server-window-alist
 | 
			
		||||
             (cons git-rebase-filename-regexp 'switch-to-buffer))
 | 
			
		||||
 | 
			
		||||
(eval-after-load 'recentf
 | 
			
		||||
  '(add-to-list 'recentf-exclude git-rebase-filename-regexp))
 | 
			
		||||
 | 
			
		||||
(add-to-list 'with-editor-file-name-history-exclude git-rebase-filename-regexp)
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'git-rebase)
 | 
			
		||||
;;; git-rebase.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,739 +0,0 @@
 | 
			
		||||
;;; magit-apply.el --- apply Git diffs  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements commands for applying Git diffs or parts
 | 
			
		||||
;; of such a diff.  The supported "apply variants" are apply, stage,
 | 
			
		||||
;; unstage, discard, and reverse - more than Git itself knows about,
 | 
			
		||||
;; at least at the porcelain level.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit-core)
 | 
			
		||||
(require 'magit-diff)
 | 
			
		||||
(require 'magit-wip)
 | 
			
		||||
 | 
			
		||||
(require 'transient) ; See #3732.
 | 
			
		||||
 | 
			
		||||
;; For `magit-apply'
 | 
			
		||||
(declare-function magit-am "magit-sequence" ())
 | 
			
		||||
(declare-function magit-patch-apply "magit-files" ())
 | 
			
		||||
;; For `magit-discard-files'
 | 
			
		||||
(declare-function magit-checkout-stage "magit-merge" (file arg))
 | 
			
		||||
(declare-function magit-checkout-read-stage "magit-merge" (file))
 | 
			
		||||
(defvar auto-revert-verbose)
 | 
			
		||||
;; For `magit-stage-untracked'
 | 
			
		||||
(declare-function magit-submodule-add-1 "magit-submodule"
 | 
			
		||||
                  (url &optional path name args))
 | 
			
		||||
(declare-function magit-submodule-read-name-for-path "magit-submodule"
 | 
			
		||||
                  (path &optional prefer-short))
 | 
			
		||||
(declare-function borg--maybe-absorb-gitdir "borg" (pkg))
 | 
			
		||||
(declare-function borg--sort-submodule-sections "borg" (file))
 | 
			
		||||
(defvar borg-user-emacs-directory)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-delete-by-moving-to-trash t
 | 
			
		||||
  "Whether Magit uses the system's trash can.
 | 
			
		||||
 | 
			
		||||
You should absolutely not disable this and also remove `discard'
 | 
			
		||||
from `magit-no-confirm'.  You shouldn't do that even if you have
 | 
			
		||||
all of the Magit-Wip modes enabled, because those modes do not
 | 
			
		||||
track any files that are not tracked in the proper branch."
 | 
			
		||||
  :package-version '(magit . "2.1.0")
 | 
			
		||||
  :group 'magit-essentials
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-unstage-committed t
 | 
			
		||||
  "Whether unstaging a committed change reverts it instead.
 | 
			
		||||
 | 
			
		||||
A committed change cannot be unstaged, because staging and
 | 
			
		||||
unstaging are actions that are concerned with the differences
 | 
			
		||||
between the index and the working tree, not with committed
 | 
			
		||||
changes.
 | 
			
		||||
 | 
			
		||||
If this option is non-nil (the default), then typing \"u\"
 | 
			
		||||
\(`magit-unstage') on a committed change, causes it to be
 | 
			
		||||
reversed in the index but not the working tree.  For more
 | 
			
		||||
information see command `magit-reverse-in-index'."
 | 
			
		||||
  :package-version '(magit . "2.4.1")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-reverse-atomically nil
 | 
			
		||||
  "Whether to reverse changes atomically.
 | 
			
		||||
 | 
			
		||||
If some changes can be reversed while others cannot, then nothing
 | 
			
		||||
is reversed if the value of this option is non-nil.  But when it
 | 
			
		||||
is nil, then the changes that can be reversed are reversed and
 | 
			
		||||
for the other changes diff files are created that contain the
 | 
			
		||||
rejected reversals."
 | 
			
		||||
  :package-version '(magit . "2.7.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-post-stage-hook nil
 | 
			
		||||
  "Hook run after staging changes.
 | 
			
		||||
This hook is run by `magit-refresh' if `this-command'
 | 
			
		||||
is a member of `magit-post-stage-hook-commands'."
 | 
			
		||||
  :package-version '(magit . "2.90.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'hook)
 | 
			
		||||
 | 
			
		||||
(defvar magit-post-stage-hook-commands
 | 
			
		||||
  '(magit-stage magit-stage-file magit-stage-modified))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-post-unstage-hook nil
 | 
			
		||||
  "Hook run after unstaging changes.
 | 
			
		||||
This hook is run by `magit-refresh' if `this-command'
 | 
			
		||||
is a member of `magit-post-unstage-hook-commands'."
 | 
			
		||||
  :package-version '(magit . "2.90.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'hook)
 | 
			
		||||
 | 
			
		||||
(defvar magit-post-unstage-hook-commands
 | 
			
		||||
  '(magit-unstage magit-unstage-file magit-unstage-all))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
;;;; Apply
 | 
			
		||||
 | 
			
		||||
(defun magit-apply (&rest args)
 | 
			
		||||
  "Apply the change at point to the working tree.
 | 
			
		||||
With a prefix argument fallback to a 3-way merge.  Doing
 | 
			
		||||
so causes the change to be applied to the index as well."
 | 
			
		||||
  (interactive (and current-prefix-arg (list "--3way")))
 | 
			
		||||
  (--when-let (magit-apply--get-selection)
 | 
			
		||||
    (pcase (list (magit-diff-type) (magit-diff-scope))
 | 
			
		||||
      (`(,(or `unstaged `staged) ,_)
 | 
			
		||||
       (user-error "Change is already in the working tree"))
 | 
			
		||||
      (`(untracked ,(or `file `files))
 | 
			
		||||
       (call-interactively 'magit-am))
 | 
			
		||||
      (`(,_ region) (magit-apply-region it args))
 | 
			
		||||
      (`(,_   hunk) (magit-apply-hunk   it args))
 | 
			
		||||
      (`(,_  hunks) (magit-apply-hunks  it args))
 | 
			
		||||
      (`(rebase-sequence file)
 | 
			
		||||
       (call-interactively 'magit-patch-apply))
 | 
			
		||||
      (`(,_   file) (magit-apply-diff   it args))
 | 
			
		||||
      (`(,_  files) (magit-apply-diffs  it args)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply--section-content (section)
 | 
			
		||||
  (buffer-substring-no-properties (if (magit-hunk-section-p section)
 | 
			
		||||
                                      (oref section start)
 | 
			
		||||
                                    (oref section content))
 | 
			
		||||
                                  (oref section end)))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply-diffs (sections &rest args)
 | 
			
		||||
  (setq sections (magit-apply--get-diffs sections))
 | 
			
		||||
  (magit-apply-patch sections args
 | 
			
		||||
                     (mapconcat
 | 
			
		||||
                      (lambda (s)
 | 
			
		||||
                        (concat (magit-diff-file-header s)
 | 
			
		||||
                                (magit-apply--section-content s)))
 | 
			
		||||
                      sections "")))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply-diff (section &rest args)
 | 
			
		||||
  (setq section (car (magit-apply--get-diffs (list section))))
 | 
			
		||||
  (magit-apply-patch section args
 | 
			
		||||
                     (concat (magit-diff-file-header section)
 | 
			
		||||
                             (magit-apply--section-content section))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply--adjust-hunk-new-starts (hunks)
 | 
			
		||||
  "Adjust new line numbers in headers of HUNKS for partial application.
 | 
			
		||||
HUNKS should be a list of ordered, contiguous hunks to be applied
 | 
			
		||||
from a file.  For example, if there is a sequence of hunks with
 | 
			
		||||
the headers
 | 
			
		||||
 | 
			
		||||
  @@ -2,6 +2,7 @@
 | 
			
		||||
  @@ -10,6 +11,7 @@
 | 
			
		||||
  @@ -18,6 +20,7 @@
 | 
			
		||||
 | 
			
		||||
and only the second and third are to be applied, they would be
 | 
			
		||||
adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
 | 
			
		||||
  (let* ((first-hunk (car hunks))
 | 
			
		||||
         (offset (if (string-match diff-hunk-header-re-unified first-hunk)
 | 
			
		||||
                     (- (string-to-number (match-string 3 first-hunk))
 | 
			
		||||
                        (string-to-number (match-string 1 first-hunk)))
 | 
			
		||||
                   (error "Hunk does not have expected header"))))
 | 
			
		||||
    (if (= offset 0)
 | 
			
		||||
        hunks
 | 
			
		||||
      (mapcar (lambda (hunk)
 | 
			
		||||
                (if (string-match diff-hunk-header-re-unified hunk)
 | 
			
		||||
                    (replace-match (number-to-string
 | 
			
		||||
                                    (- (string-to-number (match-string 3 hunk))
 | 
			
		||||
                                       offset))
 | 
			
		||||
                                   t t hunk 3)
 | 
			
		||||
                  (error "Hunk does not have expected header")))
 | 
			
		||||
              hunks))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply--adjust-hunk-new-start (hunk)
 | 
			
		||||
  (car (magit-apply--adjust-hunk-new-starts (list hunk))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply-hunks (sections &rest args)
 | 
			
		||||
  (let ((section (oref (car sections) parent)))
 | 
			
		||||
    (when (string-match "^diff --cc" (oref section value))
 | 
			
		||||
      (user-error "Cannot un-/stage resolution hunks.  Stage the whole file"))
 | 
			
		||||
    (magit-apply-patch
 | 
			
		||||
     section args
 | 
			
		||||
     (concat (oref section header)
 | 
			
		||||
             (mapconcat #'identity
 | 
			
		||||
                        (magit-apply--adjust-hunk-new-starts
 | 
			
		||||
                         (mapcar #'magit-apply--section-content sections))
 | 
			
		||||
                        "")))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply-hunk (section &rest args)
 | 
			
		||||
  (when (string-match "^diff --cc" (magit-section-parent-value section))
 | 
			
		||||
    (user-error "Cannot un-/stage resolution hunks.  Stage the whole file"))
 | 
			
		||||
  (magit-apply-patch (oref section parent) args
 | 
			
		||||
                     (concat (magit-diff-file-header section)
 | 
			
		||||
                             (magit-apply--adjust-hunk-new-start
 | 
			
		||||
                              (magit-apply--section-content section)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply-region (section &rest args)
 | 
			
		||||
  (when (string-match "^diff --cc" (magit-section-parent-value section))
 | 
			
		||||
    (user-error "Cannot un-/stage resolution hunks.  Stage the whole file"))
 | 
			
		||||
  (magit-apply-patch (oref section parent) args
 | 
			
		||||
                     (concat (magit-diff-file-header section)
 | 
			
		||||
                             (magit-apply--adjust-hunk-new-start
 | 
			
		||||
                              (magit-diff-hunk-region-patch section args)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply-patch (section:s args patch)
 | 
			
		||||
  (let* ((files (if (atom section:s)
 | 
			
		||||
                    (list (oref section:s value))
 | 
			
		||||
                  (--map (oref it value) section:s)))
 | 
			
		||||
         (command (symbol-name this-command))
 | 
			
		||||
         (command (if (and command (string-match "^magit-\\([^-]+\\)" command))
 | 
			
		||||
                      (match-string 1 command)
 | 
			
		||||
                    "apply"))
 | 
			
		||||
         (ignore-context (magit-diff-ignore-any-space-p)))
 | 
			
		||||
    (unless (magit-diff-context-p)
 | 
			
		||||
      (user-error "Not enough context to apply patch.  Increase the context"))
 | 
			
		||||
    (when (and magit-wip-before-change-mode (not inhibit-magit-refresh))
 | 
			
		||||
      (magit-wip-commit-before-change files (concat " before " command)))
 | 
			
		||||
    (with-temp-buffer
 | 
			
		||||
      (insert patch)
 | 
			
		||||
      (magit-run-git-with-input
 | 
			
		||||
       "apply" args "-p0"
 | 
			
		||||
       (and ignore-context "-C0")
 | 
			
		||||
       "--ignore-space-change" "-"))
 | 
			
		||||
    (unless inhibit-magit-refresh
 | 
			
		||||
      (when magit-wip-after-apply-mode
 | 
			
		||||
        (magit-wip-commit-after-apply files (concat " after " command)))
 | 
			
		||||
      (magit-refresh))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply--get-selection ()
 | 
			
		||||
  (or (magit-region-sections '(hunk file module) t)
 | 
			
		||||
      (let ((section (magit-current-section)))
 | 
			
		||||
        (pcase (oref section type)
 | 
			
		||||
          ((or `hunk `file `module) section)
 | 
			
		||||
          ((or `staged `unstaged `untracked
 | 
			
		||||
               `stashed-index `stashed-worktree `stashed-untracked)
 | 
			
		||||
           (oref section children))
 | 
			
		||||
          (_ (user-error "Cannot apply this, it's not a change"))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply--get-diffs (sections)
 | 
			
		||||
  (magit-section-case
 | 
			
		||||
    ([file diffstat]
 | 
			
		||||
     (--map (or (magit-get-section
 | 
			
		||||
                 (append `((file . ,(oref it value)))
 | 
			
		||||
                         (magit-section-ident magit-root-section)))
 | 
			
		||||
                (error "Cannot get required diff headers"))
 | 
			
		||||
            sections))
 | 
			
		||||
    (t sections)))
 | 
			
		||||
 | 
			
		||||
(defun magit-apply--diff-ignores-whitespace-p ()
 | 
			
		||||
  (and (cl-intersection magit-buffer-diff-args
 | 
			
		||||
                        '("--ignore-space-at-eol"
 | 
			
		||||
                          "--ignore-space-change"
 | 
			
		||||
                          "--ignore-all-space"
 | 
			
		||||
                          "--ignore-blank-lines")
 | 
			
		||||
                        :test #'equal)
 | 
			
		||||
       t))
 | 
			
		||||
 | 
			
		||||
;;;; Stage
 | 
			
		||||
 | 
			
		||||
(defun magit-stage (&optional intent)
 | 
			
		||||
  "Add the change at point to the staging area.
 | 
			
		||||
With a prefix argument, INTENT, and an untracked file (or files)
 | 
			
		||||
at point, stage the file but not its content."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (--if-let (and (derived-mode-p 'magit-mode) (magit-apply--get-selection))
 | 
			
		||||
      (pcase (list (magit-diff-type)
 | 
			
		||||
                   (magit-diff-scope)
 | 
			
		||||
                   (magit-apply--diff-ignores-whitespace-p))
 | 
			
		||||
        (`(untracked     ,_  ,_) (magit-stage-untracked intent))
 | 
			
		||||
        (`(unstaged  region  ,_) (magit-apply-region it "--cached"))
 | 
			
		||||
        (`(unstaged    hunk  ,_) (magit-apply-hunk   it "--cached"))
 | 
			
		||||
        (`(unstaged   hunks  ,_) (magit-apply-hunks  it "--cached"))
 | 
			
		||||
        (`(unstaged    file   t) (magit-apply-diff   it "--cached"))
 | 
			
		||||
        (`(unstaged   files   t) (magit-apply-diffs  it "--cached"))
 | 
			
		||||
        (`(unstaged    list   t) (magit-apply-diffs  it "--cached"))
 | 
			
		||||
        (`(unstaged    file nil) (magit-stage-1 "-u" (list (oref it value))))
 | 
			
		||||
        (`(unstaged   files nil) (magit-stage-1 "-u" (magit-region-values nil t)))
 | 
			
		||||
        (`(unstaged    list nil) (magit-stage-modified))
 | 
			
		||||
        (`(staged        ,_  ,_) (user-error "Already staged"))
 | 
			
		||||
        (`(committed     ,_  ,_) (user-error "Cannot stage committed changes"))
 | 
			
		||||
        (`(undefined     ,_  ,_) (user-error "Cannot stage this change")))
 | 
			
		||||
    (call-interactively 'magit-stage-file)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-stage-file (file)
 | 
			
		||||
  "Stage all changes to FILE.
 | 
			
		||||
With a prefix argument or when there is no file at point ask for
 | 
			
		||||
the file to be staged.  Otherwise stage the file at point without
 | 
			
		||||
requiring confirmation."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let* ((atpoint (magit-section-value-if 'file))
 | 
			
		||||
          (current (magit-file-relative-name))
 | 
			
		||||
          (choices (nconc (magit-unstaged-files)
 | 
			
		||||
                          (magit-untracked-files)))
 | 
			
		||||
          (default (car (member (or atpoint current) choices))))
 | 
			
		||||
     (list (if (or current-prefix-arg (not default))
 | 
			
		||||
               (magit-completing-read "Stage file" choices
 | 
			
		||||
                                      nil t nil nil default)
 | 
			
		||||
             default))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-stage-1 nil (list file))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-stage-modified (&optional all)
 | 
			
		||||
  "Stage all changes to files modified in the worktree.
 | 
			
		||||
Stage all new content of tracked files and remove tracked files
 | 
			
		||||
that no longer exist in the working tree from the index also.
 | 
			
		||||
With a prefix argument also stage previously untracked (but not
 | 
			
		||||
ignored) files."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (when (magit-anything-staged-p)
 | 
			
		||||
    (magit-confirm 'stage-all-changes))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-stage-1 (if all "--all" "-u") magit-buffer-diff-files)))
 | 
			
		||||
 | 
			
		||||
(defun magit-stage-1 (arg &optional files)
 | 
			
		||||
  (magit-wip-commit-before-change files " before stage")
 | 
			
		||||
  (magit-run-git "add" arg (if files (cons "--" files) "."))
 | 
			
		||||
  (when magit-auto-revert-mode
 | 
			
		||||
    (mapc #'magit-turn-on-auto-revert-mode-if-desired files))
 | 
			
		||||
  (magit-wip-commit-after-apply files " after stage"))
 | 
			
		||||
 | 
			
		||||
(defun magit-stage-untracked (&optional intent)
 | 
			
		||||
  (let* ((section (magit-current-section))
 | 
			
		||||
         (files (pcase (magit-diff-scope)
 | 
			
		||||
                  (`file  (list (oref section value)))
 | 
			
		||||
                  (`files (magit-region-values nil t))
 | 
			
		||||
                  (`list  (magit-untracked-files))))
 | 
			
		||||
         plain repos)
 | 
			
		||||
    (dolist (file files)
 | 
			
		||||
      (if (and (not (file-symlink-p file))
 | 
			
		||||
               (magit-git-repo-p file t))
 | 
			
		||||
          (push file repos)
 | 
			
		||||
        (push file plain)))
 | 
			
		||||
    (magit-wip-commit-before-change files " before stage")
 | 
			
		||||
    (when plain
 | 
			
		||||
      (magit-run-git "add" (and intent "--intent-to-add")
 | 
			
		||||
                     "--" plain)
 | 
			
		||||
      (when magit-auto-revert-mode
 | 
			
		||||
        (mapc #'magit-turn-on-auto-revert-mode-if-desired plain)))
 | 
			
		||||
    (dolist (repo repos)
 | 
			
		||||
      (save-excursion
 | 
			
		||||
        (goto-char (oref (magit-get-section
 | 
			
		||||
                          `((file . ,repo) (untracked) (status)))
 | 
			
		||||
                         start))
 | 
			
		||||
        (let* ((topdir (magit-toplevel))
 | 
			
		||||
               (package
 | 
			
		||||
                (and (equal (bound-and-true-p borg-user-emacs-directory)
 | 
			
		||||
                            topdir)
 | 
			
		||||
                     (file-name-nondirectory (directory-file-name repo)))))
 | 
			
		||||
          (magit-submodule-add-1
 | 
			
		||||
           (let ((default-directory
 | 
			
		||||
                   (file-name-as-directory (expand-file-name repo))))
 | 
			
		||||
             (or (magit-get "remote" (magit-get-some-remote) "url")
 | 
			
		||||
                 (concat (file-name-as-directory ".") repo)))
 | 
			
		||||
           repo
 | 
			
		||||
           (magit-submodule-read-name-for-path repo package))
 | 
			
		||||
          (when package
 | 
			
		||||
            (borg--sort-submodule-sections
 | 
			
		||||
             (expand-file-name ".gitmodules" topdir))
 | 
			
		||||
            (let ((default-directory borg-user-emacs-directory))
 | 
			
		||||
              (borg--maybe-absorb-gitdir package))
 | 
			
		||||
            (when (and (y-or-n-p
 | 
			
		||||
                        (format "Also build and activate `%s' drone?" package))
 | 
			
		||||
                       (fboundp 'borg-build)
 | 
			
		||||
                       (fboundp 'borg-activate))
 | 
			
		||||
              (borg-build package)
 | 
			
		||||
              (borg-activate package))))))
 | 
			
		||||
    (magit-wip-commit-after-apply files " after stage")))
 | 
			
		||||
 | 
			
		||||
;;;; Unstage
 | 
			
		||||
 | 
			
		||||
(defun magit-unstage ()
 | 
			
		||||
  "Remove the change at point from the staging area."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (--when-let (magit-apply--get-selection)
 | 
			
		||||
    (pcase (list (magit-diff-type)
 | 
			
		||||
                 (magit-diff-scope)
 | 
			
		||||
                 (magit-apply--diff-ignores-whitespace-p))
 | 
			
		||||
      (`(untracked     ,_  ,_) (user-error "Cannot unstage untracked changes"))
 | 
			
		||||
      (`(unstaged    file  ,_) (magit-unstage-intent (list (oref it value))))
 | 
			
		||||
      (`(unstaged   files  ,_) (magit-unstage-intent (magit-region-values nil t)))
 | 
			
		||||
      (`(unstaged      ,_  ,_) (user-error "Already unstaged"))
 | 
			
		||||
      (`(staged    region  ,_) (magit-apply-region it "--reverse" "--cached"))
 | 
			
		||||
      (`(staged      hunk  ,_) (magit-apply-hunk   it "--reverse" "--cached"))
 | 
			
		||||
      (`(staged     hunks  ,_) (magit-apply-hunks  it "--reverse" "--cached"))
 | 
			
		||||
      (`(staged      file   t) (magit-apply-diff   it "--reverse" "--cached"))
 | 
			
		||||
      (`(staged     files   t) (magit-apply-diffs  it "--reverse" "--cached"))
 | 
			
		||||
      (`(staged      list   t) (magit-apply-diffs  it "--reverse" "--cached"))
 | 
			
		||||
      (`(staged      file nil) (magit-unstage-1 (list (oref it value))))
 | 
			
		||||
      (`(staged     files nil) (magit-unstage-1 (magit-region-values nil t)))
 | 
			
		||||
      (`(staged      list nil) (magit-unstage-all))
 | 
			
		||||
      (`(committed     ,_  ,_) (if magit-unstage-committed
 | 
			
		||||
                                   (magit-reverse-in-index)
 | 
			
		||||
                                 (user-error "Cannot unstage committed changes")))
 | 
			
		||||
      (`(undefined     ,_  ,_) (user-error "Cannot unstage this change")))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-unstage-file (file)
 | 
			
		||||
  "Unstage all changes to FILE.
 | 
			
		||||
With a prefix argument or when there is no file at point ask for
 | 
			
		||||
the file to be unstaged.  Otherwise unstage the file at point
 | 
			
		||||
without requiring confirmation."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let* ((atpoint (magit-section-value-if 'file))
 | 
			
		||||
          (current (magit-file-relative-name))
 | 
			
		||||
          (choices (magit-staged-files))
 | 
			
		||||
          (default (car (member (or atpoint current) choices))))
 | 
			
		||||
     (list (if (or current-prefix-arg (not default))
 | 
			
		||||
               (magit-completing-read "Unstage file" choices
 | 
			
		||||
                                      nil t nil nil default)
 | 
			
		||||
             default))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-unstage-1 (list file))))
 | 
			
		||||
 | 
			
		||||
(defun magit-unstage-1 (files)
 | 
			
		||||
  (magit-wip-commit-before-change files " before unstage")
 | 
			
		||||
  (if (magit-no-commit-p)
 | 
			
		||||
      (magit-run-git "rm" "--cached" "--" files)
 | 
			
		||||
    (magit-run-git "reset" "HEAD" "--" files))
 | 
			
		||||
  (magit-wip-commit-after-apply files " after unstage"))
 | 
			
		||||
 | 
			
		||||
(defun magit-unstage-intent (files)
 | 
			
		||||
  (if-let ((staged (magit-staged-files))
 | 
			
		||||
           (intent (--filter (member it staged) files)))
 | 
			
		||||
      (magit-unstage-1 intent)
 | 
			
		||||
    (user-error "Already unstaged")))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-unstage-all ()
 | 
			
		||||
  "Remove all changes from the staging area."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (when (or (magit-anything-unstaged-p)
 | 
			
		||||
            (magit-untracked-files))
 | 
			
		||||
    (magit-confirm 'unstage-all-changes))
 | 
			
		||||
  (magit-wip-commit-before-change nil " before unstage")
 | 
			
		||||
  (magit-run-git "reset" "HEAD" "--" magit-buffer-diff-files)
 | 
			
		||||
  (magit-wip-commit-after-apply nil " after unstage"))
 | 
			
		||||
 | 
			
		||||
;;;; Discard
 | 
			
		||||
 | 
			
		||||
(defun magit-discard ()
 | 
			
		||||
  "Remove the change at point."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (--when-let (magit-apply--get-selection)
 | 
			
		||||
    (pcase (list (magit-diff-type) (magit-diff-scope))
 | 
			
		||||
      (`(committed ,_) (user-error "Cannot discard committed changes"))
 | 
			
		||||
      (`(undefined ,_) (user-error "Cannot discard this change"))
 | 
			
		||||
      (`(,_    region) (magit-discard-region it))
 | 
			
		||||
      (`(,_      hunk) (magit-discard-hunk   it))
 | 
			
		||||
      (`(,_     hunks) (magit-discard-hunks  it))
 | 
			
		||||
      (`(,_      file) (magit-discard-file   it))
 | 
			
		||||
      (`(,_     files) (magit-discard-files  it))
 | 
			
		||||
      (`(,_      list) (magit-discard-files  it)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-region (section)
 | 
			
		||||
  (magit-confirm 'discard "Discard region")
 | 
			
		||||
  (magit-discard-apply section 'magit-apply-region))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-hunk (section)
 | 
			
		||||
  (magit-confirm 'discard "Discard hunk")
 | 
			
		||||
  (magit-discard-apply section 'magit-apply-hunk))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-apply (section apply)
 | 
			
		||||
  (if (eq (magit-diff-type section) 'unstaged)
 | 
			
		||||
      (funcall apply section "--reverse")
 | 
			
		||||
    (if (magit-anything-unstaged-p
 | 
			
		||||
         nil (if (magit-file-section-p section)
 | 
			
		||||
                 (oref section value)
 | 
			
		||||
               (magit-section-parent-value section)))
 | 
			
		||||
        (progn (let ((inhibit-magit-refresh t))
 | 
			
		||||
                 (funcall apply section "--reverse" "--cached")
 | 
			
		||||
                 (funcall apply section "--reverse" "--reject"))
 | 
			
		||||
               (magit-refresh))
 | 
			
		||||
      (funcall apply section "--reverse" "--index"))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-hunks (sections)
 | 
			
		||||
  (magit-confirm 'discard (format "Discard %s hunks from %s"
 | 
			
		||||
                                  (length sections)
 | 
			
		||||
                                  (magit-section-parent-value (car sections))))
 | 
			
		||||
  (magit-discard-apply-n sections 'magit-apply-hunks))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-apply-n (sections apply)
 | 
			
		||||
  (let ((section (car sections)))
 | 
			
		||||
    (if (eq (magit-diff-type section) 'unstaged)
 | 
			
		||||
        (funcall apply sections "--reverse")
 | 
			
		||||
      (if (magit-anything-unstaged-p
 | 
			
		||||
           nil (if (magit-file-section-p section)
 | 
			
		||||
                   (oref section value)
 | 
			
		||||
                 (magit-section-parent-value section)))
 | 
			
		||||
          (progn (let ((inhibit-magit-refresh t))
 | 
			
		||||
                   (funcall apply sections "--reverse" "--cached")
 | 
			
		||||
                   (funcall apply sections "--reverse" "--reject"))
 | 
			
		||||
                 (magit-refresh))
 | 
			
		||||
        (funcall apply sections "--reverse" "--index")))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-file (section)
 | 
			
		||||
  (magit-discard-files (list section)))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-files (sections)
 | 
			
		||||
  (let ((auto-revert-verbose nil)
 | 
			
		||||
        (type (magit-diff-type (car sections)))
 | 
			
		||||
        (status (magit-file-status))
 | 
			
		||||
        files delete resurrect rename discard discard-new resolve)
 | 
			
		||||
    (dolist (section sections)
 | 
			
		||||
      (let ((file (oref section value)))
 | 
			
		||||
        (push file files)
 | 
			
		||||
        (pcase (cons (pcase type
 | 
			
		||||
                       (`staged ?X)
 | 
			
		||||
                       (`unstaged ?Y)
 | 
			
		||||
                       (`untracked ?Z))
 | 
			
		||||
                     (cddr (assoc file status)))
 | 
			
		||||
          (`(?Z) (dolist (f (magit-untracked-files nil file))
 | 
			
		||||
                   (push f delete)))
 | 
			
		||||
          ((or `(?Z ?? ??) `(?Z ?! ?!)) (push file delete))
 | 
			
		||||
          ((or `(?Z ?D ? ) `(,_ ?D ?D)) (push file delete))
 | 
			
		||||
          ((or `(,_ ?U ,_) `(,_ ,_ ?U)) (push file resolve))
 | 
			
		||||
          (`(,_ ?A ?A)                  (push file resolve))
 | 
			
		||||
          (`(?X ?M ,(or ?  ?M ?D)) (push section discard))
 | 
			
		||||
          (`(?Y ,_         ?M    ) (push section discard))
 | 
			
		||||
          (`(?X ?A         ?M    ) (push file discard-new))
 | 
			
		||||
          (`(?X ?C         ?M    ) (push file discard-new))
 | 
			
		||||
          (`(?X ?A ,(or ?     ?D)) (push file delete))
 | 
			
		||||
          (`(?X ?C ,(or ?     ?D)) (push file delete))
 | 
			
		||||
          (`(?X ?D ,(or ?  ?M   )) (push file resurrect))
 | 
			
		||||
          (`(?Y ,_            ?D ) (push file resurrect))
 | 
			
		||||
          (`(?X ?R ,(or ?  ?M ?D)) (push file rename)))))
 | 
			
		||||
    (unwind-protect
 | 
			
		||||
        (let ((inhibit-magit-refresh t))
 | 
			
		||||
          (magit-wip-commit-before-change files " before discard")
 | 
			
		||||
          (when resolve
 | 
			
		||||
            (magit-discard-files--resolve (nreverse resolve)))
 | 
			
		||||
          (when resurrect
 | 
			
		||||
            (magit-discard-files--resurrect (nreverse resurrect)))
 | 
			
		||||
          (when delete
 | 
			
		||||
            (magit-discard-files--delete (nreverse delete) status))
 | 
			
		||||
          (when rename
 | 
			
		||||
            (magit-discard-files--rename (nreverse rename) status))
 | 
			
		||||
          (when (or discard discard-new)
 | 
			
		||||
            (magit-discard-files--discard (nreverse discard)
 | 
			
		||||
                                          (nreverse discard-new)))
 | 
			
		||||
          (magit-wip-commit-after-apply files " after discard"))
 | 
			
		||||
      (magit-refresh))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-files--resolve (files)
 | 
			
		||||
  (if-let ((arg (and (cdr files)
 | 
			
		||||
                     (magit-read-char-case
 | 
			
		||||
                         (format "For these %i files\n%s\ncheckout:\n"
 | 
			
		||||
                                 (length files)
 | 
			
		||||
                                 (mapconcat (lambda (file)
 | 
			
		||||
                                              (concat "  " file))
 | 
			
		||||
                                            files "\n"))
 | 
			
		||||
                         t
 | 
			
		||||
                       (?o "[o]ur stage"   "--ours")
 | 
			
		||||
                       (?t "[t]heir stage" "--theirs")
 | 
			
		||||
                       (?c "[c]onflict"    "--merge")
 | 
			
		||||
                       (?i "decide [i]ndividually" nil)))))
 | 
			
		||||
      (dolist (file files)
 | 
			
		||||
        (magit-checkout-stage file arg))
 | 
			
		||||
    (dolist (file files)
 | 
			
		||||
      (magit-checkout-stage file (magit-checkout-read-stage file)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-files--resurrect (files)
 | 
			
		||||
  (magit-confirm-files 'resurrect files)
 | 
			
		||||
  (if (eq (magit-diff-type) 'staged)
 | 
			
		||||
      (magit-call-git "reset"  "--" files)
 | 
			
		||||
    (magit-call-git "checkout" "--" files)))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-files--delete (files status)
 | 
			
		||||
  (magit-confirm-files (if magit-delete-by-moving-to-trash 'trash 'delete)
 | 
			
		||||
                       files)
 | 
			
		||||
  (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash))
 | 
			
		||||
    (dolist (file files)
 | 
			
		||||
      (when (string-match-p "\\`\\\\?~" file)
 | 
			
		||||
        (error "Refusing to delete %S, too dangerous" file))
 | 
			
		||||
      (pcase (nth 3 (assoc file status))
 | 
			
		||||
        ((guard (memq (magit-diff-type) '(unstaged untracked)))
 | 
			
		||||
         (dired-delete-file file dired-recursive-deletes
 | 
			
		||||
                            magit-delete-by-moving-to-trash)
 | 
			
		||||
         (dired-clean-up-after-deletion file))
 | 
			
		||||
        (?\s (delete-file file t)
 | 
			
		||||
             (magit-call-git "rm" "--cached" "--" file))
 | 
			
		||||
        (?M  (let ((temp (magit-git-string "checkout-index" "--temp" file)))
 | 
			
		||||
               (string-match
 | 
			
		||||
                (format "\\(.+?\\)\t%s" (regexp-quote file)) temp)
 | 
			
		||||
               (rename-file (match-string 1 temp)
 | 
			
		||||
                            (setq temp (concat file ".~{index}~")))
 | 
			
		||||
               (delete-file temp t))
 | 
			
		||||
             (magit-call-git "rm" "--cached" "--force" "--" file))
 | 
			
		||||
        (?D  (magit-call-git "checkout" "--" file)
 | 
			
		||||
             (delete-file file t)
 | 
			
		||||
             (magit-call-git "rm" "--cached" "--force" "--" file))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-files--rename (files status)
 | 
			
		||||
  (magit-confirm 'rename "Undo rename %s" "Undo %i renames" nil
 | 
			
		||||
    (mapcar (lambda (file)
 | 
			
		||||
              (setq file (assoc file status))
 | 
			
		||||
              (format "%s -> %s" (cadr file) (car file)))
 | 
			
		||||
            files))
 | 
			
		||||
  (dolist (file files)
 | 
			
		||||
    (let ((orig (cadr (assoc file status))))
 | 
			
		||||
      (if (file-exists-p file)
 | 
			
		||||
          (progn
 | 
			
		||||
            (--when-let (file-name-directory orig)
 | 
			
		||||
              (make-directory it t))
 | 
			
		||||
            (magit-call-git "mv" file orig))
 | 
			
		||||
        (magit-call-git "rm" "--cached" "--" file)
 | 
			
		||||
        (magit-call-git "reset" "--" orig)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-discard-files--discard (sections new-files)
 | 
			
		||||
  (let ((files (--map (oref it value) sections)))
 | 
			
		||||
    (magit-confirm-files 'discard (append files new-files)
 | 
			
		||||
                         (format "Discard %s changes in" (magit-diff-type)))
 | 
			
		||||
    (if (eq (magit-diff-type (car sections)) 'unstaged)
 | 
			
		||||
        (magit-call-git "checkout" "--" files)
 | 
			
		||||
      (when new-files
 | 
			
		||||
        (magit-call-git "add"   "--" new-files)
 | 
			
		||||
        (magit-call-git "reset" "--" new-files))
 | 
			
		||||
      (let ((binaries (magit-binary-files "--cached")))
 | 
			
		||||
        (when binaries
 | 
			
		||||
          (setq sections
 | 
			
		||||
                (--remove (member (oref it value) binaries)
 | 
			
		||||
                          sections)))
 | 
			
		||||
        (cond ((= (length sections) 1)
 | 
			
		||||
               (magit-discard-apply (car sections) 'magit-apply-diff))
 | 
			
		||||
              (sections
 | 
			
		||||
               (magit-discard-apply-n sections 'magit-apply-diffs)))
 | 
			
		||||
        (when binaries
 | 
			
		||||
          (let ((modified (magit-unstaged-files t)))
 | 
			
		||||
            (setq binaries (--separate (member it modified) binaries)))
 | 
			
		||||
          (when (cadr binaries)
 | 
			
		||||
            (magit-call-git "reset" "--" (cadr binaries)))
 | 
			
		||||
          (when (car binaries)
 | 
			
		||||
            (user-error
 | 
			
		||||
             (concat
 | 
			
		||||
              "Cannot discard staged changes to binary files, "
 | 
			
		||||
              "which also have unstaged changes.  Unstage instead."))))))))
 | 
			
		||||
 | 
			
		||||
;;;; Reverse
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse (&rest args)
 | 
			
		||||
  "Reverse the change at point in the working tree.
 | 
			
		||||
With a prefix argument fallback to a 3-way merge.  Doing
 | 
			
		||||
so causes the change to be applied to the index as well."
 | 
			
		||||
  (interactive (and current-prefix-arg (list "--3way")))
 | 
			
		||||
  (--when-let (magit-apply--get-selection)
 | 
			
		||||
    (pcase (list (magit-diff-type) (magit-diff-scope))
 | 
			
		||||
      (`(untracked ,_) (user-error "Cannot reverse untracked changes"))
 | 
			
		||||
      (`(unstaged  ,_) (user-error "Cannot reverse unstaged changes"))
 | 
			
		||||
      (`(,_    region) (magit-reverse-region it args))
 | 
			
		||||
      (`(,_      hunk) (magit-reverse-hunk   it args))
 | 
			
		||||
      (`(,_     hunks) (magit-reverse-hunks  it args))
 | 
			
		||||
      (`(,_      file) (magit-reverse-file   it args))
 | 
			
		||||
      (`(,_     files) (magit-reverse-files  it args))
 | 
			
		||||
      (`(,_      list) (magit-reverse-files  it args)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-region (section args)
 | 
			
		||||
  (magit-confirm 'reverse "Reverse region")
 | 
			
		||||
  (magit-reverse-apply section 'magit-apply-region args))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-hunk (section args)
 | 
			
		||||
  (magit-confirm 'reverse "Reverse hunk")
 | 
			
		||||
  (magit-reverse-apply section 'magit-apply-hunk args))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-hunks (sections args)
 | 
			
		||||
  (magit-confirm 'reverse
 | 
			
		||||
    (format "Reverse %s hunks from %s"
 | 
			
		||||
            (length sections)
 | 
			
		||||
            (magit-section-parent-value (car sections))))
 | 
			
		||||
  (magit-reverse-apply sections 'magit-apply-hunks args))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-file (section args)
 | 
			
		||||
  (magit-reverse-files (list section) args))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-files (sections args)
 | 
			
		||||
  (pcase-let ((`(,binaries ,sections)
 | 
			
		||||
               (let ((bs (magit-binary-files
 | 
			
		||||
                          (cond ((derived-mode-p 'magit-revision-mode)
 | 
			
		||||
                                 magit-buffer-range)
 | 
			
		||||
                                ((derived-mode-p 'magit-diff-mode)
 | 
			
		||||
                                 magit-buffer-range)
 | 
			
		||||
                                (t
 | 
			
		||||
                                 "--cached")))))
 | 
			
		||||
                 (--separate (member (oref it value) bs)
 | 
			
		||||
                             sections))))
 | 
			
		||||
    (magit-confirm-files 'reverse (--map (oref it value) sections))
 | 
			
		||||
    (cond ((= (length sections) 1)
 | 
			
		||||
           (magit-reverse-apply (car sections) 'magit-apply-diff args))
 | 
			
		||||
          (sections
 | 
			
		||||
           (magit-reverse-apply sections 'magit-apply-diffs args)))
 | 
			
		||||
    (when binaries
 | 
			
		||||
      (user-error "Cannot reverse binary files"))))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-apply (section:s apply args)
 | 
			
		||||
  (funcall apply section:s "--reverse" args
 | 
			
		||||
           (and (not magit-reverse-atomically)
 | 
			
		||||
                (not (member "--3way" args))
 | 
			
		||||
                "--reject")))
 | 
			
		||||
 | 
			
		||||
(defun magit-reverse-in-index (&rest args)
 | 
			
		||||
  "Reverse the change at point in the index but not the working tree.
 | 
			
		||||
 | 
			
		||||
Use this command to extract a change from `HEAD', while leaving
 | 
			
		||||
it in the working tree, so that it can later be committed using
 | 
			
		||||
a separate commit.  A typical workflow would be:
 | 
			
		||||
 | 
			
		||||
0. Optionally make sure that there are no uncommitted changes.
 | 
			
		||||
1. Visit the `HEAD' commit and navigate to the change that should
 | 
			
		||||
   not have been included in that commit.
 | 
			
		||||
2. Type \"u\" (`magit-unstage') to reverse it in the index.
 | 
			
		||||
   This assumes that `magit-unstage-committed-changes' is non-nil.
 | 
			
		||||
3. Type \"c e\" to extend `HEAD' with the staged changes,
 | 
			
		||||
   including those that were already staged before.
 | 
			
		||||
4. Optionally stage the remaining changes using \"s\" or \"S\"
 | 
			
		||||
   and then type \"c c\" to create a new commit."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-reverse (cons "--cached" args)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-apply)
 | 
			
		||||
;;; magit-apply.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,269 +0,0 @@
 | 
			
		||||
;;; magit-autorevert.el --- revert buffers when files in repository change  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'cl-lib)
 | 
			
		||||
(require 'dash)
 | 
			
		||||
 | 
			
		||||
(require 'magit-git)
 | 
			
		||||
 | 
			
		||||
(require 'autorevert)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defgroup magit-auto-revert nil
 | 
			
		||||
  "Revert buffers when files in repository change."
 | 
			
		||||
  :link '(custom-group-link auto-revert)
 | 
			
		||||
  :link '(info-link "(magit)Automatic Reverting of File-Visiting Buffers")
 | 
			
		||||
  :group 'auto-revert
 | 
			
		||||
  :group 'magit-essentials
 | 
			
		||||
  :group 'magit-modes)
 | 
			
		||||
 | 
			
		||||
(defcustom auto-revert-buffer-list-filter nil
 | 
			
		||||
  "Filter that determines which buffers `auto-revert-buffers' reverts.
 | 
			
		||||
 | 
			
		||||
This option is provided by Magit, which also advises
 | 
			
		||||
`auto-revert-buffers' to respect it.  Magit users who do not turn
 | 
			
		||||
on the local mode `auto-revert-mode' themselves, are best served
 | 
			
		||||
by setting the value to `magit-auto-revert-repository-buffer-p'.
 | 
			
		||||
 | 
			
		||||
However the default is nil, so as not to disturb users who do use
 | 
			
		||||
the local mode directly.  If you experience delays when running
 | 
			
		||||
Magit commands, then you should consider using one of the
 | 
			
		||||
predicates provided by Magit - especially if you also use Tramp.
 | 
			
		||||
 | 
			
		||||
Users who do turn on `auto-revert-mode' in buffers in which Magit
 | 
			
		||||
doesn't do that for them, should likely not use any filter.
 | 
			
		||||
Users who turn on `global-auto-revert-mode', do not have to worry
 | 
			
		||||
about this option, because it is disregarded if the global mode
 | 
			
		||||
is enabled."
 | 
			
		||||
  :package-version '(magit . "2.4.2")
 | 
			
		||||
  :group 'auto-revert
 | 
			
		||||
  :group 'magit-auto-revert
 | 
			
		||||
  :group 'magit-related
 | 
			
		||||
  :type '(radio (const :tag "No filter" nil)
 | 
			
		||||
                (function-item magit-auto-revert-buffer-p)
 | 
			
		||||
                (function-item magit-auto-revert-repository-buffer-p)
 | 
			
		||||
                function))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-auto-revert-tracked-only t
 | 
			
		||||
  "Whether `magit-auto-revert-mode' only reverts tracked files."
 | 
			
		||||
  :package-version '(magit . "2.4.0")
 | 
			
		||||
  :group 'magit-auto-revert
 | 
			
		||||
  :type 'boolean
 | 
			
		||||
  :set (lambda (var val)
 | 
			
		||||
         (set var val)
 | 
			
		||||
         (when (and (bound-and-true-p magit-auto-revert-mode)
 | 
			
		||||
                    (featurep 'magit-autorevert))
 | 
			
		||||
           (magit-auto-revert-mode -1)
 | 
			
		||||
           (magit-auto-revert-mode))))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-auto-revert-immediately t
 | 
			
		||||
  "Whether Magit reverts buffers immediately.
 | 
			
		||||
 | 
			
		||||
If this is non-nil and either `global-auto-revert-mode' or
 | 
			
		||||
`magit-auto-revert-mode' is enabled, then Magit immediately
 | 
			
		||||
reverts buffers by explicitly calling `auto-revert-buffers'
 | 
			
		||||
after running Git for side-effects.
 | 
			
		||||
 | 
			
		||||
If `auto-revert-use-notify' is non-nil (and file notifications
 | 
			
		||||
are actually supported), then `magit-auto-revert-immediately'
 | 
			
		||||
does not have to be non-nil, because the reverts happen
 | 
			
		||||
immediately anyway.
 | 
			
		||||
 | 
			
		||||
If `magit-auto-revert-immediately' and `auto-revert-use-notify'
 | 
			
		||||
are both nil, then reverts happen after `auto-revert-interval'
 | 
			
		||||
seconds of user inactivity.  That is not desirable."
 | 
			
		||||
  :package-version '(magit . "2.4.0")
 | 
			
		||||
  :group 'magit-auto-revert
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
;;; Mode
 | 
			
		||||
 | 
			
		||||
(defun magit-turn-on-auto-revert-mode-if-desired (&optional file)
 | 
			
		||||
  (if file
 | 
			
		||||
      (--when-let (find-buffer-visiting file)
 | 
			
		||||
        (with-current-buffer it
 | 
			
		||||
          (magit-turn-on-auto-revert-mode-if-desired)))
 | 
			
		||||
    (when (and buffer-file-name
 | 
			
		||||
               (file-readable-p buffer-file-name)
 | 
			
		||||
               (or (< emacs-major-version 27)
 | 
			
		||||
                   (with-no-warnings
 | 
			
		||||
                     (condition-case nil
 | 
			
		||||
                         (executable-find magit-git-executable t) ; see #3684
 | 
			
		||||
                       (wrong-number-of-arguments t)))) ; very old 27 built
 | 
			
		||||
               (magit-toplevel)
 | 
			
		||||
               (or (not magit-auto-revert-tracked-only)
 | 
			
		||||
                   (magit-file-tracked-p buffer-file-name))
 | 
			
		||||
               (not auto-revert-mode)         ; see #3014
 | 
			
		||||
               (not global-auto-revert-mode)) ; see #3460
 | 
			
		||||
      (auto-revert-mode 1))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(define-globalized-minor-mode magit-auto-revert-mode auto-revert-mode
 | 
			
		||||
  magit-turn-on-auto-revert-mode-if-desired
 | 
			
		||||
  :package-version '(magit . "2.4.0")
 | 
			
		||||
  :link '(info-link "(magit)Automatic Reverting of File-Visiting Buffers")
 | 
			
		||||
  :group 'magit-auto-revert
 | 
			
		||||
  :group 'magit-essentials
 | 
			
		||||
  ;; - When `global-auto-revert-mode' is enabled, then this mode is
 | 
			
		||||
  ;;   redundant.
 | 
			
		||||
  ;; - In all other cases enable the mode because if buffers are not
 | 
			
		||||
  ;;   automatically reverted that would make many very common tasks
 | 
			
		||||
  ;;   much more cumbersome.
 | 
			
		||||
  :init-value (not (or global-auto-revert-mode
 | 
			
		||||
                       noninteractive)))
 | 
			
		||||
;; - Unfortunately `:init-value t' only sets the value of the mode
 | 
			
		||||
;;   variable but does not cause the mode function to be called.
 | 
			
		||||
;; - I don't think it works like this on purpose, but since one usually
 | 
			
		||||
;;   should not enable global modes by default, it is understandable.
 | 
			
		||||
;; - If the user has set the variable `magit-auto-revert-mode' to nil
 | 
			
		||||
;;   after loading magit (instead of doing so before loading magit or
 | 
			
		||||
;;   by using the function), then we should still respect that setting.
 | 
			
		||||
;; - If the user sets one of these variables after loading magit and
 | 
			
		||||
;;   after `after-init-hook' has run, then that won't have an effect
 | 
			
		||||
;;   and there is nothing we can do about it.
 | 
			
		||||
(defun magit-auto-revert-mode--init-kludge ()
 | 
			
		||||
  "This is an internal kludge to be used on `after-init-hook'.
 | 
			
		||||
Do not use this function elsewhere, and don't remove it from
 | 
			
		||||
the `after-init-hook'.  For more information see the comments
 | 
			
		||||
and code surrounding the definition of this function."
 | 
			
		||||
  (if magit-auto-revert-mode
 | 
			
		||||
      (let ((start (current-time)))
 | 
			
		||||
        (magit-message "Turning on magit-auto-revert-mode...")
 | 
			
		||||
        (magit-auto-revert-mode 1)
 | 
			
		||||
        (magit-message
 | 
			
		||||
         "Turning on magit-auto-revert-mode...done%s"
 | 
			
		||||
         (let ((elapsed (float-time (time-subtract nil start))))
 | 
			
		||||
           (if (> elapsed 0.2)
 | 
			
		||||
               (format " (%.3fs, %s buffers checked)" elapsed
 | 
			
		||||
                       (length (buffer-list)))
 | 
			
		||||
             ""))))
 | 
			
		||||
    (magit-auto-revert-mode -1)))
 | 
			
		||||
(if after-init-time
 | 
			
		||||
    ;; Since `after-init-hook' has already been
 | 
			
		||||
    ;; run, turn the mode on or off right now.
 | 
			
		||||
    (magit-auto-revert-mode--init-kludge)
 | 
			
		||||
  ;; By the time the init file has been fully loaded the
 | 
			
		||||
  ;; values of the relevant variables might have changed.
 | 
			
		||||
  (add-hook 'after-init-hook #'magit-auto-revert-mode--init-kludge t))
 | 
			
		||||
 | 
			
		||||
(put 'magit-auto-revert-mode 'function-documentation
 | 
			
		||||
     "Toggle Magit Auto Revert mode.
 | 
			
		||||
If called interactively, enable Magit Auto Revert mode if ARG is
 | 
			
		||||
positive, and disable it if ARG is zero or negative.  If called
 | 
			
		||||
from Lisp, also enable the mode if ARG is omitted or nil, and
 | 
			
		||||
toggle it if ARG is `toggle'; disable the mode otherwise.
 | 
			
		||||
 | 
			
		||||
Magit Auto Revert mode is a global minor mode that reverts
 | 
			
		||||
buffers associated with a file that is located inside a Git
 | 
			
		||||
repository when the file changes on disk.  Use `auto-revert-mode'
 | 
			
		||||
to revert a particular buffer.  Or use `global-auto-revert-mode'
 | 
			
		||||
to revert all file-visiting buffers, not just those that visit
 | 
			
		||||
a file located inside a Git repository.
 | 
			
		||||
 | 
			
		||||
This global mode works by turning on the buffer-local mode
 | 
			
		||||
`auto-revert-mode' at the time a buffer is first created.  The
 | 
			
		||||
local mode is turned on if the visited file is being tracked in
 | 
			
		||||
a Git repository at the time when the buffer is created.
 | 
			
		||||
 | 
			
		||||
If `magit-auto-revert-tracked-only' is non-nil (the default),
 | 
			
		||||
then only tracked files are reverted.  But if you stage a
 | 
			
		||||
previously untracked file using `magit-stage', then this mode
 | 
			
		||||
notices that.
 | 
			
		||||
 | 
			
		||||
Unlike `global-auto-revert-mode', this mode never reverts any
 | 
			
		||||
buffers that are not visiting files.
 | 
			
		||||
 | 
			
		||||
The behavior of this mode can be customized using the options
 | 
			
		||||
in the `autorevert' and `magit-autorevert' groups.
 | 
			
		||||
 | 
			
		||||
This function calls the hook `magit-auto-revert-mode-hook'.
 | 
			
		||||
 | 
			
		||||
Like nearly every mode, this mode should be enabled or disabled
 | 
			
		||||
by calling the respective mode function, the reason being that
 | 
			
		||||
changing the state of a mode involves more than merely toggling
 | 
			
		||||
a single switch, so setting the mode variable is not enough.
 | 
			
		||||
Also, you should not use `after-init-hook' to disable this mode.")
 | 
			
		||||
 | 
			
		||||
(defun magit-auto-revert-buffers ()
 | 
			
		||||
  (when (and magit-auto-revert-immediately
 | 
			
		||||
             (or global-auto-revert-mode
 | 
			
		||||
                 (and magit-auto-revert-mode auto-revert-buffer-list)))
 | 
			
		||||
    (let ((auto-revert-buffer-list-filter
 | 
			
		||||
           (or auto-revert-buffer-list-filter
 | 
			
		||||
               #'magit-auto-revert-repository-buffer-p)))
 | 
			
		||||
      (auto-revert-buffers))))
 | 
			
		||||
 | 
			
		||||
(defvar magit-auto-revert-toplevel nil)
 | 
			
		||||
 | 
			
		||||
(defvar magit-auto-revert-counter 1
 | 
			
		||||
  "Incremented each time `auto-revert-buffers' is called.")
 | 
			
		||||
 | 
			
		||||
(defun magit-auto-revert-buffer-p (buffer)
 | 
			
		||||
  "Return non-nil if BUFFER visits a file inside the current repository.
 | 
			
		||||
The current repository is the one containing `default-directory'.
 | 
			
		||||
If there is no current repository, then return t for any BUFFER."
 | 
			
		||||
  (magit-auto-revert-repository-buffer-p buffer t))
 | 
			
		||||
 | 
			
		||||
(defun magit-auto-revert-repository-buffer-p (buffer &optional fallback)
 | 
			
		||||
  "Return non-nil if BUFFER visits a file inside the current repository.
 | 
			
		||||
The current repository is the one containing `default-directory'.
 | 
			
		||||
If there is no current repository, then return FALLBACK (which
 | 
			
		||||
defaults to nil) for any BUFFER."
 | 
			
		||||
  ;; Call `magit-toplevel' just once per cycle.
 | 
			
		||||
  (unless (and magit-auto-revert-toplevel
 | 
			
		||||
               (= (cdr magit-auto-revert-toplevel)
 | 
			
		||||
                  magit-auto-revert-counter))
 | 
			
		||||
    (setq magit-auto-revert-toplevel
 | 
			
		||||
          (cons (or (magit-toplevel) 'no-repo)
 | 
			
		||||
                magit-auto-revert-counter)))
 | 
			
		||||
  (let ((top (car magit-auto-revert-toplevel)))
 | 
			
		||||
    (if (eq top 'no-repo)
 | 
			
		||||
        fallback
 | 
			
		||||
      (let ((dir (buffer-local-value 'default-directory buffer)))
 | 
			
		||||
        (and (equal (file-remote-p dir)
 | 
			
		||||
                    (file-remote-p top))
 | 
			
		||||
             ;; ^ `tramp-handle-file-in-directory-p' lacks this optimization.
 | 
			
		||||
             (file-in-directory-p dir top))))))
 | 
			
		||||
 | 
			
		||||
(defun auto-revert-buffers--buffer-list-filter (fn)
 | 
			
		||||
  (cl-incf magit-auto-revert-counter)
 | 
			
		||||
  (if (or global-auto-revert-mode
 | 
			
		||||
          (not auto-revert-buffer-list)
 | 
			
		||||
          (not auto-revert-buffer-list-filter))
 | 
			
		||||
      (funcall fn)
 | 
			
		||||
    (let ((auto-revert-buffer-list
 | 
			
		||||
           (-filter auto-revert-buffer-list-filter
 | 
			
		||||
                    auto-revert-buffer-list)))
 | 
			
		||||
      (funcall fn))
 | 
			
		||||
    (unless auto-revert-timer
 | 
			
		||||
      (auto-revert-set-timer))))
 | 
			
		||||
 | 
			
		||||
(advice-add 'auto-revert-buffers :around
 | 
			
		||||
            'auto-revert-buffers--buffer-list-filter)
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-autorevert)
 | 
			
		||||
;;; magit-autorevert.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,239 +0,0 @@
 | 
			
		||||
;;; magit-bisect.el --- bisect support for Magit  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2011-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Use a binary search to find the commit that introduced a bug.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-bisect-show-graph t
 | 
			
		||||
  "Whether to use `--graph' in the log showing commits yet to be bisected."
 | 
			
		||||
  :package-version '(magit . "2.8.0")
 | 
			
		||||
  :group 'magit-status
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defface magit-bisect-good
 | 
			
		||||
  '((t :foreground "DarkOliveGreen"))
 | 
			
		||||
  "Face for good bisect revisions."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-bisect-skip
 | 
			
		||||
  '((t :foreground "DarkGoldenrod"))
 | 
			
		||||
  "Face for skipped bisect revisions."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-bisect-bad
 | 
			
		||||
  '((t :foreground "IndianRed4"))
 | 
			
		||||
  "Face for bad bisect revisions."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-bisect "magit-bisect" nil t)
 | 
			
		||||
(transient-define-prefix magit-bisect ()
 | 
			
		||||
  "Narrow in on the commit that introduced a bug."
 | 
			
		||||
  :man-page "git-bisect"
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   :if-not magit-bisect-in-progress-p
 | 
			
		||||
   ("B" "Start"        magit-bisect-start)
 | 
			
		||||
   ("s" "Start script" magit-bisect-run)]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   :if magit-bisect-in-progress-p
 | 
			
		||||
   ("B" "Bad"          magit-bisect-bad)
 | 
			
		||||
   ("g" "Good"         magit-bisect-good)
 | 
			
		||||
   ("k" "Skip"         magit-bisect-skip)
 | 
			
		||||
   ("r" "Reset"        magit-bisect-reset)
 | 
			
		||||
   ("s" "Run script"   magit-bisect-run)])
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-bisect-start (bad good)
 | 
			
		||||
  "Start a bisect session.
 | 
			
		||||
 | 
			
		||||
Bisecting a bug means to find the commit that introduced it.
 | 
			
		||||
This command starts such a bisect session by asking for a know
 | 
			
		||||
good and a bad commit.  To move the session forward use the
 | 
			
		||||
other actions from the bisect transient command (\
 | 
			
		||||
\\<magit-status-mode-map>\\[magit-bisect])."
 | 
			
		||||
  (interactive (if (magit-bisect-in-progress-p)
 | 
			
		||||
                   (user-error "Already bisecting")
 | 
			
		||||
                 (magit-bisect-start-read-args)))
 | 
			
		||||
  (unless (magit-rev-ancestor-p good bad)
 | 
			
		||||
    (user-error
 | 
			
		||||
     "The good revision (%s) has to be an ancestor of the bad one (%s)"
 | 
			
		||||
     good bad))
 | 
			
		||||
  (when (magit-anything-modified-p)
 | 
			
		||||
    (user-error "Cannot bisect with uncommitted changes"))
 | 
			
		||||
  (magit-git-bisect "start" (list bad good) t))
 | 
			
		||||
 | 
			
		||||
(defun magit-bisect-start-read-args ()
 | 
			
		||||
  (let  ((b (magit-read-branch-or-commit "Start bisect with bad revision")))
 | 
			
		||||
    (list b (magit-read-other-branch-or-commit "Good revision" b))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-bisect-reset ()
 | 
			
		||||
  "After bisecting, cleanup bisection state and return to original `HEAD'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-confirm 'reset-bisect)
 | 
			
		||||
  (magit-run-git "bisect" "reset")
 | 
			
		||||
  (ignore-errors (delete-file (magit-git-dir "BISECT_CMD_OUTPUT"))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-bisect-good ()
 | 
			
		||||
  "While bisecting, mark the current commit as good.
 | 
			
		||||
Use this after you have asserted that the commit does not contain
 | 
			
		||||
the bug in question."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-git-bisect "good"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-bisect-bad ()
 | 
			
		||||
  "While bisecting, mark the current commit as bad.
 | 
			
		||||
Use this after you have asserted that the commit does contain the
 | 
			
		||||
bug in question."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-git-bisect "bad"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-bisect-skip ()
 | 
			
		||||
  "While bisecting, skip the current commit.
 | 
			
		||||
Use this if for some reason the current commit is not a good one
 | 
			
		||||
to test.  This command lets Git choose a different one."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-git-bisect "skip"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-bisect-run (cmdline &optional bad good)
 | 
			
		||||
  "Bisect automatically by running commands after each step.
 | 
			
		||||
 | 
			
		||||
Unlike `git bisect run' this can be used before bisecting has
 | 
			
		||||
begun.  In that case it behaves like `git bisect start; git
 | 
			
		||||
bisect run'."
 | 
			
		||||
  (interactive (let ((args (and (not (magit-bisect-in-progress-p))
 | 
			
		||||
                                (magit-bisect-start-read-args))))
 | 
			
		||||
                 (cons (read-shell-command "Bisect shell command: ") args)))
 | 
			
		||||
  (when (and bad good)
 | 
			
		||||
    (magit-bisect-start bad good))
 | 
			
		||||
  (magit-git-bisect "run" (list shell-file-name shell-command-switch cmdline)))
 | 
			
		||||
 | 
			
		||||
(defun magit-git-bisect (subcommand &optional args no-assert)
 | 
			
		||||
  (unless (or no-assert (magit-bisect-in-progress-p))
 | 
			
		||||
    (user-error "Not bisecting"))
 | 
			
		||||
  (message "Bisecting...")
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git-async "bisect" subcommand args))
 | 
			
		||||
  (set-process-sentinel
 | 
			
		||||
   magit-this-process
 | 
			
		||||
   (lambda (process event)
 | 
			
		||||
     (when (memq (process-status process) '(exit signal))
 | 
			
		||||
       (if (> (process-exit-status process) 0)
 | 
			
		||||
           (magit-process-sentinel process event)
 | 
			
		||||
         (process-put process 'inhibit-refresh t)
 | 
			
		||||
         (magit-process-sentinel process event)
 | 
			
		||||
         (when (buffer-live-p (process-buffer process))
 | 
			
		||||
           (with-current-buffer (process-buffer process)
 | 
			
		||||
             (when-let ((section (get-text-property (point) 'magit-section))
 | 
			
		||||
                        (output (buffer-substring-no-properties
 | 
			
		||||
                                 (oref section content)
 | 
			
		||||
                                 (oref section end))))
 | 
			
		||||
               (with-temp-file (magit-git-dir "BISECT_CMD_OUTPUT")
 | 
			
		||||
                 (insert output)))))
 | 
			
		||||
         (magit-refresh))
 | 
			
		||||
       (message "Bisecting...done")))))
 | 
			
		||||
 | 
			
		||||
;;; Sections
 | 
			
		||||
 | 
			
		||||
(defun magit-bisect-in-progress-p ()
 | 
			
		||||
  (file-exists-p (magit-git-dir "BISECT_LOG")))
 | 
			
		||||
 | 
			
		||||
(defun magit-insert-bisect-output ()
 | 
			
		||||
  "While bisecting, insert section with output from `git bisect'."
 | 
			
		||||
  (when (magit-bisect-in-progress-p)
 | 
			
		||||
    (let* ((lines
 | 
			
		||||
            (or (magit-file-lines (magit-git-dir "BISECT_CMD_OUTPUT"))
 | 
			
		||||
                (list "Bisecting: (no saved bisect output)"
 | 
			
		||||
                      "It appears you have invoked `git bisect' from a shell."
 | 
			
		||||
                      "There is nothing wrong with that, we just cannot display"
 | 
			
		||||
                      "anything useful here.  Consult the shell output instead.")))
 | 
			
		||||
           (done-re "^\\([a-z0-9]\\{40\\}\\) is the first bad commit$")
 | 
			
		||||
           (bad-line (or (and (string-match done-re (car lines))
 | 
			
		||||
                              (pop lines))
 | 
			
		||||
                         (--first (string-match done-re it) lines))))
 | 
			
		||||
      (magit-insert-section ((eval (if bad-line 'commit 'bisect-output))
 | 
			
		||||
                             (and bad-line (match-string 1 bad-line)))
 | 
			
		||||
        (magit-insert-heading
 | 
			
		||||
          (propertize (or bad-line (pop lines))
 | 
			
		||||
                      'font-lock-face 'magit-section-heading))
 | 
			
		||||
        (dolist (line lines)
 | 
			
		||||
          (insert line "\n"))))
 | 
			
		||||
    (insert "\n")))
 | 
			
		||||
 | 
			
		||||
(defun magit-insert-bisect-rest ()
 | 
			
		||||
  "While bisecting, insert section visualizing the bisect state."
 | 
			
		||||
  (when (magit-bisect-in-progress-p)
 | 
			
		||||
    (magit-insert-section (bisect-view)
 | 
			
		||||
      (magit-insert-heading "Bisect Rest:")
 | 
			
		||||
      (magit-git-wash (apply-partially 'magit-log-wash-log 'bisect-vis)
 | 
			
		||||
        "bisect" "visualize" "git" "log"
 | 
			
		||||
        "--format=%h%x00%D%x00%s" "--decorate=full"
 | 
			
		||||
        (and magit-bisect-show-graph "--graph")))))
 | 
			
		||||
 | 
			
		||||
(defun magit-insert-bisect-log ()
 | 
			
		||||
  "While bisecting, insert section logging bisect progress."
 | 
			
		||||
  (when (magit-bisect-in-progress-p)
 | 
			
		||||
    (magit-insert-section (bisect-log)
 | 
			
		||||
      (magit-insert-heading "Bisect Log:")
 | 
			
		||||
      (magit-git-wash #'magit-wash-bisect-log "bisect" "log")
 | 
			
		||||
      (insert ?\n))))
 | 
			
		||||
 | 
			
		||||
(defun magit-wash-bisect-log (_args)
 | 
			
		||||
  (let (beg)
 | 
			
		||||
    (while (progn (setq beg (point-marker))
 | 
			
		||||
                  (re-search-forward "^\\(git bisect [^\n]+\n\\)" nil t))
 | 
			
		||||
      (magit-bind-match-strings (heading) nil
 | 
			
		||||
        (magit-delete-match)
 | 
			
		||||
        (save-restriction
 | 
			
		||||
          (narrow-to-region beg (point))
 | 
			
		||||
          (goto-char (point-min))
 | 
			
		||||
          (magit-insert-section (bisect-item heading t)
 | 
			
		||||
            (insert (propertize heading 'font-lock-face
 | 
			
		||||
                                'magit-section-secondary-heading))
 | 
			
		||||
            (magit-insert-heading)
 | 
			
		||||
            (magit-wash-sequence
 | 
			
		||||
             (apply-partially 'magit-log-wash-rev 'bisect-log
 | 
			
		||||
                              (magit-abbrev-length)))
 | 
			
		||||
            (insert ?\n)))))
 | 
			
		||||
    (when (re-search-forward
 | 
			
		||||
           "# first bad commit: \\[\\([a-z0-9]\\{40\\}\\)\\] [^\n]+\n" nil t)
 | 
			
		||||
      (magit-bind-match-strings (hash) nil
 | 
			
		||||
        (magit-delete-match)
 | 
			
		||||
        (magit-insert-section (bisect-item)
 | 
			
		||||
          (insert hash " is the first bad commit\n"))))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-bisect)
 | 
			
		||||
;;; magit-bisect.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,944 +0,0 @@
 | 
			
		||||
;;; magit-blame.el --- blame support for Magit  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2012-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Annotates each line in file-visiting buffer with information from
 | 
			
		||||
;; the revision which last modified the line.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defgroup magit-blame nil
 | 
			
		||||
  "Blame support for Magit."
 | 
			
		||||
  :link '(info-link "(magit)Blaming")
 | 
			
		||||
  :group 'magit-modes)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-styles
 | 
			
		||||
  '((headings
 | 
			
		||||
     (heading-format   . "%-20a %C %s\n"))
 | 
			
		||||
    (margin
 | 
			
		||||
     (margin-format    . (" %s%f" " %C %a" " %H"))
 | 
			
		||||
     (margin-width     . 42)
 | 
			
		||||
     (margin-face      . magit-blame-margin)
 | 
			
		||||
     (margin-body-face . (magit-blame-dimmed)))
 | 
			
		||||
    (highlight
 | 
			
		||||
     (highlight-face   . magit-blame-highlight))
 | 
			
		||||
    (lines
 | 
			
		||||
     (show-lines       . t)
 | 
			
		||||
     (show-message     . t)))
 | 
			
		||||
  "List of styles used to visualize blame information.
 | 
			
		||||
 | 
			
		||||
Each entry has the form (IDENT (KEY . VALUE)...).  IDENT has
 | 
			
		||||
to be a symbol uniquely identifying the style.  The following
 | 
			
		||||
KEYs are recognized:
 | 
			
		||||
 | 
			
		||||
 `show-lines'
 | 
			
		||||
    Whether to prefix each chunk of lines with a thin line.
 | 
			
		||||
    This has no effect if `heading-format' is non-nil.
 | 
			
		||||
 `show-message'
 | 
			
		||||
    Whether to display a commit's summary line in the echo area
 | 
			
		||||
    when crossing chunks.
 | 
			
		||||
 `highlight-face'
 | 
			
		||||
    Face used to highlight the first line of each chunk.
 | 
			
		||||
    If this is nil, then those lines are not highlighted.
 | 
			
		||||
 `heading-format'
 | 
			
		||||
    String specifying the information to be shown above each
 | 
			
		||||
    chunk of lines.  It must end with a newline character.
 | 
			
		||||
 `margin-format'
 | 
			
		||||
    String specifying the information to be shown in the left
 | 
			
		||||
    buffer margin.  It must NOT end with a newline character.
 | 
			
		||||
    This can also be a list of formats used for the lines at
 | 
			
		||||
    the same positions within the chunk.  If the chunk has
 | 
			
		||||
    more lines than formats are specified, then the last is
 | 
			
		||||
    repeated.
 | 
			
		||||
 `margin-width'
 | 
			
		||||
    Width of the margin, provided `margin-format' is non-nil.
 | 
			
		||||
 `margin-face'
 | 
			
		||||
    Face used in the margin, provided `margin-format' is
 | 
			
		||||
    non-nil.  This face is used in combination with the faces
 | 
			
		||||
    that are specific to the used %-specs.  If this is nil,
 | 
			
		||||
    then `magit-blame-margin' is used.
 | 
			
		||||
 `margin-body-face'
 | 
			
		||||
    Face used in the margin for all but first line of a chunk.
 | 
			
		||||
    This face is used in combination with the faces that are
 | 
			
		||||
    specific to the used %-specs.  This can also be a list of
 | 
			
		||||
    faces (usually one face), in which case only these faces
 | 
			
		||||
    are used and the %-spec faces are ignored.  A good value
 | 
			
		||||
    might be `(magit-blame-dimmed)'.  If this is nil, then
 | 
			
		||||
    the same face as for the first line is used.
 | 
			
		||||
 | 
			
		||||
The following %-specs can be used in `heading-format' and
 | 
			
		||||
`margin-format':
 | 
			
		||||
 | 
			
		||||
  %H    hash              using face `magit-blame-hash'
 | 
			
		||||
  %s    summary           using face `magit-blame-summary'
 | 
			
		||||
  %a    author            using face `magit-blame-name'
 | 
			
		||||
  %A    author time       using face `magit-blame-date'
 | 
			
		||||
  %c    committer         using face `magit-blame-name'
 | 
			
		||||
  %C    committer time    using face `magit-blame-date'
 | 
			
		||||
 | 
			
		||||
Additionally if `margin-format' ends with %f, then the string
 | 
			
		||||
that is displayed in the margin is made at least `margin-width'
 | 
			
		||||
characters wide, which may be desirable if the used face sets
 | 
			
		||||
the background color.
 | 
			
		||||
 | 
			
		||||
The style used in the current buffer can be cycled from the blame
 | 
			
		||||
popup.  Blame commands (except `magit-blame-echo') use the first
 | 
			
		||||
style as the initial style when beginning to blame in a buffer."
 | 
			
		||||
  :package-version '(magit . "2.13.0")
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type 'string)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-echo-style 'lines
 | 
			
		||||
  "The blame visualization style used by `magit-blame-echo'.
 | 
			
		||||
A symbol that has to be used as the identifier for one of the
 | 
			
		||||
styles defined in `magit-blame-styles'."
 | 
			
		||||
  :package-version '(magit . "2.13.0")
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type 'symbol)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-time-format "%F %H:%M"
 | 
			
		||||
  "Format for time strings in blame headings."
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type 'string)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-read-only t
 | 
			
		||||
  "Whether to initially make the blamed buffer read-only."
 | 
			
		||||
  :package-version '(magit . "2.13.0")
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-disable-modes '(fci-mode yascroll-bar-mode)
 | 
			
		||||
  "List of modes not compatible with Magit-Blame mode.
 | 
			
		||||
This modes are turned off when Magit-Blame mode is turned on,
 | 
			
		||||
and then turned on again when turning off the latter."
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type '(repeat (symbol :tag "Mode")))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-mode-lighter " Blame"
 | 
			
		||||
  "The mode-line lighter of the Magit-Blame mode."
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type '(choice (const :tag "No lighter" "") string))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-blame-goto-chunk-hook
 | 
			
		||||
  '(magit-blame-maybe-update-revision-buffer
 | 
			
		||||
    magit-blame-maybe-show-message)
 | 
			
		||||
  "Hook run after point entered another chunk."
 | 
			
		||||
  :package-version '(magit . "2.13.0")
 | 
			
		||||
  :group 'magit-blame
 | 
			
		||||
  :type 'hook
 | 
			
		||||
  :get 'magit-hook-custom-get
 | 
			
		||||
  :options '(magit-blame-maybe-update-revision-buffer
 | 
			
		||||
             magit-blame-maybe-show-message))
 | 
			
		||||
 | 
			
		||||
;;; Faces
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-highlight
 | 
			
		||||
  `((((class color) (background light))
 | 
			
		||||
     ,@(and (>= emacs-major-version 27) '(:extend t))
 | 
			
		||||
     :background "grey80"
 | 
			
		||||
     :foreground "black")
 | 
			
		||||
    (((class color) (background dark))
 | 
			
		||||
     ,@(and (>= emacs-major-version 27) '(:extend t))
 | 
			
		||||
     :background "grey25"
 | 
			
		||||
     :foreground "white"))
 | 
			
		||||
  "Face used for highlighting when blaming.
 | 
			
		||||
Also see option `magit-blame-styles'."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-margin
 | 
			
		||||
  '((t :inherit magit-blame-highlight
 | 
			
		||||
       :weight normal
 | 
			
		||||
       :slant normal))
 | 
			
		||||
  "Face used for the blame margin by default when blaming.
 | 
			
		||||
Also see option `magit-blame-styles'."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-dimmed
 | 
			
		||||
  '((t :inherit magit-dimmed
 | 
			
		||||
       :weight normal
 | 
			
		||||
       :slant normal))
 | 
			
		||||
  "Face used for the blame margin in some cases when blaming.
 | 
			
		||||
Also see option `magit-blame-styles'."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-heading
 | 
			
		||||
  `((t ,@(and (>= emacs-major-version 27) '(:extend t))
 | 
			
		||||
       :inherit magit-blame-highlight
 | 
			
		||||
       :weight normal
 | 
			
		||||
       :slant normal))
 | 
			
		||||
  "Face used for blame headings by default when blaming.
 | 
			
		||||
Also see option `magit-blame-styles'."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-summary nil
 | 
			
		||||
  "Face used for commit summaries when blaming."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-hash nil
 | 
			
		||||
  "Face used for commit hashes when blaming."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-name nil
 | 
			
		||||
  "Face used for author and committer names when blaming."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-blame-date nil
 | 
			
		||||
  "Face used for dates when blaming."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
;;; Chunks
 | 
			
		||||
 | 
			
		||||
(defclass magit-blame-chunk ()
 | 
			
		||||
  (;; <orig-rev> <orig-line> <final-line> <num-lines>
 | 
			
		||||
   (orig-rev   :initarg :orig-rev)
 | 
			
		||||
   (orig-line  :initarg :orig-line)
 | 
			
		||||
   (final-line :initarg :final-line)
 | 
			
		||||
   (num-lines  :initarg :num-lines)
 | 
			
		||||
   ;; previous <prev-rev> <prev-file>
 | 
			
		||||
   (prev-rev   :initform nil)
 | 
			
		||||
   (prev-file  :initform nil)
 | 
			
		||||
   ;; filename <orig-file>
 | 
			
		||||
   (orig-file)))
 | 
			
		||||
 | 
			
		||||
(defun magit-current-blame-chunk (&optional type)
 | 
			
		||||
  (or (and (not (and type (not (eq type magit-blame-type))))
 | 
			
		||||
           (magit-blame-chunk-at (point)))
 | 
			
		||||
      (and type
 | 
			
		||||
           (let ((rev  (or magit-buffer-refname magit-buffer-revision))
 | 
			
		||||
                 (file (magit-file-relative-name nil (not magit-buffer-file-name)))
 | 
			
		||||
                 (line (format "%i,+1" (line-number-at-pos))))
 | 
			
		||||
             (unless file
 | 
			
		||||
               (error "Buffer does not visit a tracked file"))
 | 
			
		||||
             (with-temp-buffer
 | 
			
		||||
               (magit-with-toplevel
 | 
			
		||||
                 (magit-git-insert
 | 
			
		||||
                  "blame" "--porcelain"
 | 
			
		||||
                  (if (memq magit-blame-type '(final removal))
 | 
			
		||||
                      (cons "--reverse" (magit-blame-arguments))
 | 
			
		||||
                    (magit-blame-arguments))
 | 
			
		||||
                  "-L" line rev "--" file)
 | 
			
		||||
                 (goto-char (point-min))
 | 
			
		||||
                 (car (magit-blame--parse-chunk type))))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-chunk-at (pos)
 | 
			
		||||
  (--some (overlay-get it 'magit-blame-chunk)
 | 
			
		||||
          (overlays-at pos)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--overlay-at (&optional pos key)
 | 
			
		||||
  (unless pos
 | 
			
		||||
    (setq pos (point)))
 | 
			
		||||
  (--first (overlay-get it (or key 'magit-blame-chunk))
 | 
			
		||||
           (nconc (overlays-at pos)
 | 
			
		||||
                  (overlays-in pos pos))))
 | 
			
		||||
 | 
			
		||||
;;; Keymaps
 | 
			
		||||
 | 
			
		||||
(defvar magit-blame-mode-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map (kbd "C-c C-q") 'magit-blame-quit)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for `magit-blame-mode'.
 | 
			
		||||
Note that most blaming key bindings are defined
 | 
			
		||||
in `magit-blame-read-only-mode-map' instead.")
 | 
			
		||||
 | 
			
		||||
(defvar magit-blame-read-only-mode-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map (kbd "C-m") 'magit-show-commit)
 | 
			
		||||
    (define-key map (kbd   "p") 'magit-blame-previous-chunk)
 | 
			
		||||
    (define-key map (kbd   "P") 'magit-blame-previous-chunk-same-commit)
 | 
			
		||||
    (define-key map (kbd   "n") 'magit-blame-next-chunk)
 | 
			
		||||
    (define-key map (kbd   "N") 'magit-blame-next-chunk-same-commit)
 | 
			
		||||
    (define-key map (kbd   "b") 'magit-blame-addition)
 | 
			
		||||
    (define-key map (kbd   "r") 'magit-blame-removal)
 | 
			
		||||
    (define-key map (kbd   "f") 'magit-blame-reverse)
 | 
			
		||||
    (define-key map (kbd   "B") 'magit-blame)
 | 
			
		||||
    (define-key map (kbd   "c") 'magit-blame-cycle-style)
 | 
			
		||||
    (define-key map (kbd   "q") 'magit-blame-quit)
 | 
			
		||||
    (define-key map (kbd "M-w") 'magit-blame-copy-hash)
 | 
			
		||||
    (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up)
 | 
			
		||||
    (define-key map (kbd "S-SPC") 'magit-diff-show-or-scroll-down)
 | 
			
		||||
    (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for `magit-blame-read-only-mode'.")
 | 
			
		||||
 | 
			
		||||
;;; Modes
 | 
			
		||||
;;;; Variables
 | 
			
		||||
 | 
			
		||||
(defvar-local magit-blame-buffer-read-only nil)
 | 
			
		||||
(defvar-local magit-blame-cache nil)
 | 
			
		||||
(defvar-local magit-blame-disabled-modes nil)
 | 
			
		||||
(defvar-local magit-blame-process nil)
 | 
			
		||||
(defvar-local magit-blame-recursive-p nil)
 | 
			
		||||
(defvar-local magit-blame-type nil)
 | 
			
		||||
(defvar-local magit-blame-separator nil)
 | 
			
		||||
(defvar-local magit-blame-previous-chunk nil)
 | 
			
		||||
 | 
			
		||||
(defvar-local magit-blame--style nil)
 | 
			
		||||
 | 
			
		||||
(defsubst magit-blame--style-get (key)
 | 
			
		||||
  (cdr (assoc key (cdr magit-blame--style))))
 | 
			
		||||
 | 
			
		||||
;;;; Base Mode
 | 
			
		||||
 | 
			
		||||
(define-minor-mode magit-blame-mode
 | 
			
		||||
  "Display blame information inline."
 | 
			
		||||
  :lighter magit-blame-mode-lighter
 | 
			
		||||
  (cond (magit-blame-mode
 | 
			
		||||
         (when (called-interactively-p 'any)
 | 
			
		||||
           (setq magit-blame-mode nil)
 | 
			
		||||
           (user-error
 | 
			
		||||
            (concat "Don't call `magit-blame-mode' directly; "
 | 
			
		||||
                    "instead use `magit-blame'")))
 | 
			
		||||
         (add-hook 'after-save-hook     'magit-blame--refresh t t)
 | 
			
		||||
         (add-hook 'post-command-hook   'magit-blame-goto-chunk-hook t t)
 | 
			
		||||
         (add-hook 'before-revert-hook  'magit-blame--remove-overlays t t)
 | 
			
		||||
         (add-hook 'after-revert-hook   'magit-blame--refresh t t)
 | 
			
		||||
         (add-hook 'read-only-mode-hook 'magit-blame-toggle-read-only t t)
 | 
			
		||||
         (setq magit-blame-buffer-read-only buffer-read-only)
 | 
			
		||||
         (when (or magit-blame-read-only magit-buffer-file-name)
 | 
			
		||||
           (read-only-mode 1))
 | 
			
		||||
         (dolist (mode magit-blame-disable-modes)
 | 
			
		||||
           (when (and (boundp mode) (symbol-value mode))
 | 
			
		||||
             (funcall mode -1)
 | 
			
		||||
             (push mode magit-blame-disabled-modes)))
 | 
			
		||||
         (setq magit-blame-separator (magit-blame--format-separator))
 | 
			
		||||
         (unless magit-blame--style
 | 
			
		||||
           (setq magit-blame--style (car magit-blame-styles)))
 | 
			
		||||
         (magit-blame--update-margin))
 | 
			
		||||
        (t
 | 
			
		||||
         (when (process-live-p magit-blame-process)
 | 
			
		||||
           (kill-process magit-blame-process)
 | 
			
		||||
           (while magit-blame-process
 | 
			
		||||
             (sit-for 0.01))) ; avoid racing the sentinel
 | 
			
		||||
         (remove-hook 'after-save-hook     'magit-blame--refresh t)
 | 
			
		||||
         (remove-hook 'post-command-hook   'magit-blame-goto-chunk-hook t)
 | 
			
		||||
         (remove-hook 'before-revert-hook  'magit-blame--remove-overlays t)
 | 
			
		||||
         (remove-hook 'after-revert-hook   'magit-blame--refresh t)
 | 
			
		||||
         (remove-hook 'read-only-mode-hook 'magit-blame-toggle-read-only t)
 | 
			
		||||
         (unless magit-blame-buffer-read-only
 | 
			
		||||
           (read-only-mode -1))
 | 
			
		||||
         (magit-blame-read-only-mode -1)
 | 
			
		||||
         (dolist (mode magit-blame-disabled-modes)
 | 
			
		||||
           (funcall mode 1))
 | 
			
		||||
         (kill-local-variable 'magit-blame-disabled-modes)
 | 
			
		||||
         (kill-local-variable 'magit-blame-type)
 | 
			
		||||
         (kill-local-variable 'magit-blame--style)
 | 
			
		||||
         (magit-blame--update-margin)
 | 
			
		||||
         (magit-blame--remove-overlays))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--refresh ()
 | 
			
		||||
  (magit-blame--run (magit-blame-arguments)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-goto-chunk-hook ()
 | 
			
		||||
  (let ((chunk (magit-blame-chunk-at (point))))
 | 
			
		||||
    (when (cl-typep chunk 'magit-blame-chunk)
 | 
			
		||||
      (unless (eq chunk magit-blame-previous-chunk)
 | 
			
		||||
        (run-hooks 'magit-blame-goto-chunk-hook))
 | 
			
		||||
      (setq magit-blame-previous-chunk chunk))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-toggle-read-only ()
 | 
			
		||||
  (magit-blame-read-only-mode (if buffer-read-only 1 -1)))
 | 
			
		||||
 | 
			
		||||
;;;; Read-Only Mode
 | 
			
		||||
 | 
			
		||||
(define-minor-mode magit-blame-read-only-mode
 | 
			
		||||
  "Provide keybindings for Magit-Blame mode.
 | 
			
		||||
 | 
			
		||||
This minor-mode provides the key bindings for Magit-Blame mode,
 | 
			
		||||
but only when Read-Only mode is also enabled because these key
 | 
			
		||||
bindings would otherwise conflict badly with regular bindings.
 | 
			
		||||
 | 
			
		||||
When both Magit-Blame mode and Read-Only mode are enabled, then
 | 
			
		||||
this mode gets automatically enabled too and when one of these
 | 
			
		||||
modes is toggled, then this mode also gets toggled automatically.
 | 
			
		||||
 | 
			
		||||
\\{magit-blame-read-only-mode-map}")
 | 
			
		||||
 | 
			
		||||
;;;; Kludges
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-put-keymap-before-view-mode ()
 | 
			
		||||
  "Put `magit-blame-read-only-mode' ahead of `view-mode' in `minor-mode-map-alist'."
 | 
			
		||||
  (--when-let (assq 'magit-blame-read-only-mode
 | 
			
		||||
                    (cl-member 'view-mode minor-mode-map-alist :key #'car))
 | 
			
		||||
    (setq minor-mode-map-alist
 | 
			
		||||
          (cons it (delq it minor-mode-map-alist))))
 | 
			
		||||
  (remove-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode))
 | 
			
		||||
 | 
			
		||||
(add-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode)
 | 
			
		||||
 | 
			
		||||
;;; Process
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--run (args)
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (unless magit-blame-mode
 | 
			
		||||
      (magit-blame-mode 1))
 | 
			
		||||
    (message "Blaming...")
 | 
			
		||||
    (magit-blame-run-process
 | 
			
		||||
     (or magit-buffer-refname magit-buffer-revision)
 | 
			
		||||
     (magit-file-relative-name nil (not magit-buffer-file-name))
 | 
			
		||||
     (if (memq magit-blame-type '(final removal))
 | 
			
		||||
         (cons "--reverse" args)
 | 
			
		||||
       args)
 | 
			
		||||
     (list (line-number-at-pos (window-start))
 | 
			
		||||
           (line-number-at-pos (1- (window-end nil t)))))
 | 
			
		||||
    (set-process-sentinel magit-this-process
 | 
			
		||||
                          'magit-blame-process-quickstart-sentinel)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-run-process (revision file args &optional lines)
 | 
			
		||||
  (let ((process (magit-parse-git-async
 | 
			
		||||
                  "blame" "--incremental" args
 | 
			
		||||
                  (and lines (list "-L" (apply #'format "%s,%s" lines)))
 | 
			
		||||
                  revision "--" file)))
 | 
			
		||||
    (set-process-filter   process 'magit-blame-process-filter)
 | 
			
		||||
    (set-process-sentinel process 'magit-blame-process-sentinel)
 | 
			
		||||
    (process-put process 'arguments (list revision file args))
 | 
			
		||||
    (setq magit-blame-cache (make-hash-table :test 'equal))
 | 
			
		||||
    (setq magit-blame-process process)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-process-quickstart-sentinel (process event)
 | 
			
		||||
  (when (memq (process-status process) '(exit signal))
 | 
			
		||||
    (magit-blame-process-sentinel process event t)
 | 
			
		||||
    (magit-blame-assert-buffer process)
 | 
			
		||||
    (with-current-buffer (process-get process 'command-buf)
 | 
			
		||||
      (when magit-blame-mode
 | 
			
		||||
        (let ((default-directory (magit-toplevel)))
 | 
			
		||||
          (apply #'magit-blame-run-process
 | 
			
		||||
                 (process-get process 'arguments)))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-process-sentinel (process _event &optional quiet)
 | 
			
		||||
  (let ((status (process-status process)))
 | 
			
		||||
    (when (memq status '(exit signal))
 | 
			
		||||
      (kill-buffer (process-buffer process))
 | 
			
		||||
      (if (and (eq status 'exit)
 | 
			
		||||
               (zerop (process-exit-status process)))
 | 
			
		||||
          (unless quiet
 | 
			
		||||
            (message "Blaming...done"))
 | 
			
		||||
        (magit-blame-assert-buffer process)
 | 
			
		||||
        (with-current-buffer (process-get process 'command-buf)
 | 
			
		||||
          (if magit-blame-mode
 | 
			
		||||
              (progn (magit-blame-mode -1)
 | 
			
		||||
                     (message "Blaming...failed"))
 | 
			
		||||
            (message "Blaming...aborted"))))
 | 
			
		||||
      (kill-local-variable 'magit-blame-process))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-process-filter (process string)
 | 
			
		||||
  (internal-default-process-filter process string)
 | 
			
		||||
  (let ((buf  (process-get process 'command-buf))
 | 
			
		||||
        (pos  (process-get process 'parsed))
 | 
			
		||||
        (mark (process-mark process))
 | 
			
		||||
        type cache)
 | 
			
		||||
    (with-current-buffer buf
 | 
			
		||||
      (setq type  magit-blame-type)
 | 
			
		||||
      (setq cache magit-blame-cache))
 | 
			
		||||
    (with-current-buffer (process-buffer process)
 | 
			
		||||
      (goto-char pos)
 | 
			
		||||
      (while (and (< (point) mark)
 | 
			
		||||
                  (save-excursion (re-search-forward "^filename .+\n" nil t)))
 | 
			
		||||
        (pcase-let* ((`(,chunk ,revinfo)
 | 
			
		||||
                      (magit-blame--parse-chunk type))
 | 
			
		||||
                     (rev (oref chunk orig-rev)))
 | 
			
		||||
          (if revinfo
 | 
			
		||||
              (puthash rev revinfo cache)
 | 
			
		||||
            (setq revinfo
 | 
			
		||||
                  (or (gethash rev cache)
 | 
			
		||||
                      (puthash rev (magit-blame--commit-alist rev) cache))))
 | 
			
		||||
          (magit-blame--make-overlays buf chunk revinfo))
 | 
			
		||||
        (process-put process 'parsed (point))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--parse-chunk (type)
 | 
			
		||||
  (let (chunk revinfo)
 | 
			
		||||
    (looking-at "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)")
 | 
			
		||||
    (with-slots (orig-rev orig-file prev-rev prev-file)
 | 
			
		||||
        (setq chunk (magit-blame-chunk
 | 
			
		||||
                     :orig-rev                     (match-string 1)
 | 
			
		||||
                     :orig-line  (string-to-number (match-string 2))
 | 
			
		||||
                     :final-line (string-to-number (match-string 3))
 | 
			
		||||
                     :num-lines  (string-to-number (match-string 4))))
 | 
			
		||||
      (forward-line)
 | 
			
		||||
      (let (done)
 | 
			
		||||
        (while (not done)
 | 
			
		||||
          (cond ((looking-at "^filename \\(.+\\)")
 | 
			
		||||
                 (setq done t)
 | 
			
		||||
                 (setf orig-file (match-string 1)))
 | 
			
		||||
                ((looking-at "^previous \\(.\\{40\\}\\) \\(.+\\)")
 | 
			
		||||
                 (setf prev-rev  (match-string 1))
 | 
			
		||||
                 (setf prev-file (match-string 2)))
 | 
			
		||||
                ((looking-at "^\\([^ ]+\\) \\(.+\\)")
 | 
			
		||||
                 (push (cons (match-string 1)
 | 
			
		||||
                             (match-string 2)) revinfo)))
 | 
			
		||||
          (forward-line)))
 | 
			
		||||
      (when (and (eq type 'removal) prev-rev)
 | 
			
		||||
        (cl-rotatef orig-rev  prev-rev)
 | 
			
		||||
        (cl-rotatef orig-file prev-file)
 | 
			
		||||
        (setq revinfo nil)))
 | 
			
		||||
    (list chunk revinfo)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--commit-alist (rev)
 | 
			
		||||
  (cl-mapcar 'cons
 | 
			
		||||
             '("summary"
 | 
			
		||||
               "author" "author-time" "author-tz"
 | 
			
		||||
               "committer" "committer-time" "committer-tz")
 | 
			
		||||
             (split-string (magit-rev-format "%s\v%an\v%ad\v%cn\v%cd" rev
 | 
			
		||||
                                             "--date=format:%s\v%z")
 | 
			
		||||
                           "\v")))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-assert-buffer (process)
 | 
			
		||||
  (unless (buffer-live-p (process-get process 'command-buf))
 | 
			
		||||
    (kill-process process)
 | 
			
		||||
    (user-error "Buffer being blamed has been killed")))
 | 
			
		||||
 | 
			
		||||
;;; Display
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--make-overlays (buf chunk revinfo)
 | 
			
		||||
  (with-current-buffer buf
 | 
			
		||||
    (save-excursion
 | 
			
		||||
      (save-restriction
 | 
			
		||||
        (widen)
 | 
			
		||||
        (goto-char (point-min))
 | 
			
		||||
        (forward-line (1- (oref chunk final-line)))
 | 
			
		||||
        (let ((beg (point))
 | 
			
		||||
              (end (save-excursion
 | 
			
		||||
                     (forward-line (oref chunk num-lines))
 | 
			
		||||
                     (point))))
 | 
			
		||||
          (magit-blame--remove-overlays beg end)
 | 
			
		||||
          (magit-blame--make-margin-overlays chunk revinfo beg end)
 | 
			
		||||
          (magit-blame--make-heading-overlay chunk revinfo beg end)
 | 
			
		||||
          (magit-blame--make-highlight-overlay   chunk beg))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--make-margin-overlays (chunk revinfo _beg end)
 | 
			
		||||
  (save-excursion
 | 
			
		||||
    (let ((line 0))
 | 
			
		||||
      (while (< (point) end)
 | 
			
		||||
        (magit-blame--make-margin-overlay chunk revinfo line)
 | 
			
		||||
        (forward-line)
 | 
			
		||||
        (cl-incf line)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--make-margin-overlay (chunk revinfo line)
 | 
			
		||||
  (let* ((end (line-end-position))
 | 
			
		||||
         ;; If possible avoid putting this on the first character
 | 
			
		||||
         ;; of the line to avoid a conflict with the line overlay.
 | 
			
		||||
         (beg (min (1+ (line-beginning-position)) end))
 | 
			
		||||
         (ov  (make-overlay beg end)))
 | 
			
		||||
    (overlay-put ov 'magit-blame-chunk chunk)
 | 
			
		||||
    (overlay-put ov 'magit-blame-revinfo revinfo)
 | 
			
		||||
    (overlay-put ov 'magit-blame-margin line)
 | 
			
		||||
    (magit-blame--update-margin-overlay ov)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--make-heading-overlay (chunk revinfo beg end)
 | 
			
		||||
  (let ((ov (make-overlay beg end)))
 | 
			
		||||
    (overlay-put ov 'magit-blame-chunk chunk)
 | 
			
		||||
    (overlay-put ov 'magit-blame-revinfo revinfo)
 | 
			
		||||
    (overlay-put ov 'magit-blame-heading t)
 | 
			
		||||
    (magit-blame--update-heading-overlay ov)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--make-highlight-overlay (chunk beg)
 | 
			
		||||
  (let ((ov (make-overlay beg (1+ (line-end-position)))))
 | 
			
		||||
    (overlay-put ov 'magit-blame-chunk chunk)
 | 
			
		||||
    (overlay-put ov 'magit-blame-highlight t)
 | 
			
		||||
    (magit-blame--update-highlight-overlay ov)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--update-margin ()
 | 
			
		||||
  (setq left-margin-width (or (magit-blame--style-get 'margin-width) 0))
 | 
			
		||||
  (set-window-buffer (selected-window) (current-buffer)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--update-overlays ()
 | 
			
		||||
  (save-restriction
 | 
			
		||||
    (widen)
 | 
			
		||||
    (dolist (ov (overlays-in (point-min) (point-max)))
 | 
			
		||||
      (cond ((overlay-get ov 'magit-blame-heading)
 | 
			
		||||
             (magit-blame--update-heading-overlay ov))
 | 
			
		||||
            ((overlay-get ov 'magit-blame-margin)
 | 
			
		||||
             (magit-blame--update-margin-overlay ov))
 | 
			
		||||
            ((overlay-get ov 'magit-blame-highlight)
 | 
			
		||||
             (magit-blame--update-highlight-overlay ov))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--update-margin-overlay (ov)
 | 
			
		||||
  (overlay-put
 | 
			
		||||
   ov 'before-string
 | 
			
		||||
   (and (magit-blame--style-get 'margin-width)
 | 
			
		||||
        (propertize
 | 
			
		||||
         "o" 'display
 | 
			
		||||
         (list (list 'margin 'left-margin)
 | 
			
		||||
               (let ((line   (overlay-get ov 'magit-blame-margin))
 | 
			
		||||
                     (format (magit-blame--style-get 'margin-format))
 | 
			
		||||
                     (face   (magit-blame--style-get 'margin-face)))
 | 
			
		||||
                 (magit-blame--format-string
 | 
			
		||||
                  ov
 | 
			
		||||
                  (or (and (atom format)
 | 
			
		||||
                           format)
 | 
			
		||||
                      (nth line format)
 | 
			
		||||
                      (car (last format)))
 | 
			
		||||
                  (or (and (not (zerop line))
 | 
			
		||||
                           (magit-blame--style-get 'margin-body-face))
 | 
			
		||||
                      face
 | 
			
		||||
                      'magit-blame-margin))))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--update-heading-overlay (ov)
 | 
			
		||||
  (overlay-put
 | 
			
		||||
   ov 'before-string
 | 
			
		||||
   (--if-let (magit-blame--style-get 'heading-format)
 | 
			
		||||
       (magit-blame--format-string ov it 'magit-blame-heading)
 | 
			
		||||
     (and (magit-blame--style-get 'show-lines)
 | 
			
		||||
          (or (not (magit-blame--style-get 'margin-format))
 | 
			
		||||
              (save-excursion
 | 
			
		||||
                (goto-char (overlay-start ov))
 | 
			
		||||
                ;; Special case of the special case described in
 | 
			
		||||
                ;; `magit-blame--make-margin-overlay'.  For empty
 | 
			
		||||
                ;; lines it is not possible to show both overlays
 | 
			
		||||
                ;; without the line being to high.
 | 
			
		||||
                (not (= (point) (line-end-position)))))
 | 
			
		||||
          magit-blame-separator))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--update-highlight-overlay (ov)
 | 
			
		||||
  (overlay-put ov 'font-lock-face (magit-blame--style-get 'highlight-face)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--format-string (ov format face)
 | 
			
		||||
  (let* ((chunk   (overlay-get ov 'magit-blame-chunk))
 | 
			
		||||
         (revinfo (overlay-get ov 'magit-blame-revinfo))
 | 
			
		||||
         (key     (list format face))
 | 
			
		||||
         (string  (cdr (assoc key revinfo))))
 | 
			
		||||
    (unless string
 | 
			
		||||
      (setq string
 | 
			
		||||
            (and format
 | 
			
		||||
                 (magit-blame--format-string-1 (oref chunk orig-rev)
 | 
			
		||||
                                               revinfo format face)))
 | 
			
		||||
      (nconc revinfo (list (cons key string))))
 | 
			
		||||
    string))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--format-string-1 (rev revinfo format face)
 | 
			
		||||
  (let ((str
 | 
			
		||||
         (if (equal rev "0000000000000000000000000000000000000000")
 | 
			
		||||
             (propertize (concat (if (string-prefix-p "\s" format) "\s" "")
 | 
			
		||||
                                 "Not Yet Committed"
 | 
			
		||||
                                 (if (string-suffix-p "\n" format) "\n" ""))
 | 
			
		||||
                         'font-lock-face face)
 | 
			
		||||
           (magit--format-spec
 | 
			
		||||
            (propertize format 'font-lock-face face)
 | 
			
		||||
            (cl-flet* ((p0 (s f)
 | 
			
		||||
                           (propertize s 'font-lock-face
 | 
			
		||||
                                       (if face
 | 
			
		||||
                                           (if (listp face)
 | 
			
		||||
                                               face
 | 
			
		||||
                                             (list f face))
 | 
			
		||||
                                         f)))
 | 
			
		||||
                       (p1 (k f)
 | 
			
		||||
                           (p0 (cdr (assoc k revinfo)) f))
 | 
			
		||||
                       (p2 (k1 k2 f)
 | 
			
		||||
                           (p0 (magit-blame--format-time-string
 | 
			
		||||
                                (cdr (assoc k1 revinfo))
 | 
			
		||||
                                (cdr (assoc k2 revinfo)))
 | 
			
		||||
                               f)))
 | 
			
		||||
              `((?H . ,(p0 rev         'magit-blame-hash))
 | 
			
		||||
                (?s . ,(p1 "summary"   'magit-blame-summary))
 | 
			
		||||
                (?a . ,(p1 "author"    'magit-blame-name))
 | 
			
		||||
                (?c . ,(p1 "committer" 'magit-blame-name))
 | 
			
		||||
                (?A . ,(p2 "author-time"    "author-tz"    'magit-blame-date))
 | 
			
		||||
                (?C . ,(p2 "committer-time" "committer-tz" 'magit-blame-date))
 | 
			
		||||
                (?f . "")))))))
 | 
			
		||||
    (if-let ((width (and (string-suffix-p "%f" format)
 | 
			
		||||
                         (magit-blame--style-get 'margin-width))))
 | 
			
		||||
        (concat str
 | 
			
		||||
                (propertize (make-string (max 0 (- width (length str))) ?\s)
 | 
			
		||||
                            'font-lock-face face))
 | 
			
		||||
      str)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--format-separator ()
 | 
			
		||||
  (propertize
 | 
			
		||||
   (concat (propertize "\s" 'display '(space :height (2)))
 | 
			
		||||
           (propertize "\n" 'line-height t))
 | 
			
		||||
   'font-lock-face (list :background
 | 
			
		||||
                         (face-attribute 'magit-blame-heading
 | 
			
		||||
                                         :background nil t))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--format-time-string (time tz)
 | 
			
		||||
  (let* ((time-format (or (magit-blame--style-get 'time-format)
 | 
			
		||||
                          magit-blame-time-format))
 | 
			
		||||
         (tz-in-second (and (string-match "%z" time-format)
 | 
			
		||||
                            (car (last (parse-time-string tz))))))
 | 
			
		||||
    (format-time-string time-format
 | 
			
		||||
                        (seconds-to-time (string-to-number time))
 | 
			
		||||
                        tz-in-second)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--remove-overlays (&optional beg end)
 | 
			
		||||
  (save-restriction
 | 
			
		||||
    (widen)
 | 
			
		||||
    (dolist (ov (overlays-in (or beg (point-min))
 | 
			
		||||
                             (or end (point-max))))
 | 
			
		||||
      (when (overlay-get ov 'magit-blame-chunk)
 | 
			
		||||
        (delete-overlay ov)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-maybe-show-message ()
 | 
			
		||||
  (when (magit-blame--style-get 'show-message)
 | 
			
		||||
    (let ((message-log-max 0))
 | 
			
		||||
      (if-let ((msg (cdr (assoc "summary"
 | 
			
		||||
                               (gethash (oref (magit-current-blame-chunk)
 | 
			
		||||
                                              orig-rev)
 | 
			
		||||
                                        magit-blame-cache)))))
 | 
			
		||||
          (progn (set-text-properties 0 (length msg) nil msg)
 | 
			
		||||
                 (message msg))
 | 
			
		||||
        (message "Commit data not available yet.  Still blaming.")))))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-blame-echo "magit-blame" nil t)
 | 
			
		||||
(transient-define-suffix magit-blame-echo (args)
 | 
			
		||||
  "For each line show the revision in which it was added.
 | 
			
		||||
Show the information about the chunk at point in the echo area
 | 
			
		||||
when moving between chunks.  Unlike other blaming commands, do
 | 
			
		||||
not turn on `read-only-mode'."
 | 
			
		||||
  :if (lambda ()
 | 
			
		||||
        (and buffer-file-name
 | 
			
		||||
             (or (not magit-blame-mode)
 | 
			
		||||
                 buffer-read-only)))
 | 
			
		||||
  (interactive (list (magit-blame-arguments)))
 | 
			
		||||
  (when magit-buffer-file-name
 | 
			
		||||
    (user-error "Blob buffers aren't supported"))
 | 
			
		||||
  (setq-local magit-blame--style
 | 
			
		||||
              (assq magit-blame-echo-style magit-blame-styles))
 | 
			
		||||
  (setq-local magit-blame-disable-modes
 | 
			
		||||
              (cons 'eldoc-mode magit-blame-disable-modes))
 | 
			
		||||
  (if (not magit-blame-mode)
 | 
			
		||||
      (let ((magit-blame-read-only nil))
 | 
			
		||||
        (magit-blame--pre-blame-assert 'addition)
 | 
			
		||||
        (magit-blame--pre-blame-setup  'addition)
 | 
			
		||||
        (magit-blame--run args))
 | 
			
		||||
    (read-only-mode -1)
 | 
			
		||||
    (magit-blame--update-overlays)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-blame-addition "magit-blame" nil t)
 | 
			
		||||
(transient-define-suffix magit-blame-addition (args)
 | 
			
		||||
  "For each line show the revision in which it was added."
 | 
			
		||||
  (interactive (list (magit-blame-arguments)))
 | 
			
		||||
  (magit-blame--pre-blame-assert 'addition)
 | 
			
		||||
  (magit-blame--pre-blame-setup  'addition)
 | 
			
		||||
  (magit-blame--run args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-blame-removal "magit-blame" nil t)
 | 
			
		||||
(transient-define-suffix magit-blame-removal (args)
 | 
			
		||||
  "For each line show the revision in which it was removed."
 | 
			
		||||
  :if-nil 'buffer-file-name
 | 
			
		||||
  (interactive (list (magit-blame-arguments)))
 | 
			
		||||
  (unless magit-buffer-file-name
 | 
			
		||||
    (user-error "Only blob buffers can be blamed in reverse"))
 | 
			
		||||
  (magit-blame--pre-blame-assert 'removal)
 | 
			
		||||
  (magit-blame--pre-blame-setup  'removal)
 | 
			
		||||
  (magit-blame--run args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-blame-reverse "magit-blame" nil t)
 | 
			
		||||
(transient-define-suffix magit-blame-reverse (args)
 | 
			
		||||
  "For each line show the last revision in which it still exists."
 | 
			
		||||
  :if-nil 'buffer-file-name
 | 
			
		||||
  (interactive (list (magit-blame-arguments)))
 | 
			
		||||
  (unless magit-buffer-file-name
 | 
			
		||||
    (user-error "Only blob buffers can be blamed in reverse"))
 | 
			
		||||
  (magit-blame--pre-blame-assert 'final)
 | 
			
		||||
  (magit-blame--pre-blame-setup  'final)
 | 
			
		||||
  (magit-blame--run args))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--pre-blame-assert (type)
 | 
			
		||||
  (unless (magit-toplevel)
 | 
			
		||||
    (magit--not-inside-repository-error))
 | 
			
		||||
  (if (and magit-blame-mode
 | 
			
		||||
           (eq type magit-blame-type))
 | 
			
		||||
      (if-let ((chunk (magit-current-blame-chunk)))
 | 
			
		||||
          (unless (oref chunk prev-rev)
 | 
			
		||||
            (user-error "Chunk has no further history"))
 | 
			
		||||
        (user-error "Commit data not available yet.  Still blaming."))
 | 
			
		||||
    (unless (magit-file-relative-name nil (not magit-buffer-file-name))
 | 
			
		||||
      (if buffer-file-name
 | 
			
		||||
          (user-error "Buffer isn't visiting a tracked file")
 | 
			
		||||
        (user-error "Buffer isn't visiting a file")))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame--pre-blame-setup (type)
 | 
			
		||||
  (when magit-blame-mode
 | 
			
		||||
    (if (eq type magit-blame-type)
 | 
			
		||||
        (let ((style magit-blame--style))
 | 
			
		||||
          (magit-blame-visit-other-file)
 | 
			
		||||
          (setq-local magit-blame--style style)
 | 
			
		||||
          (setq-local magit-blame-recursive-p t)
 | 
			
		||||
          ;; Set window-start for the benefit of quickstart.
 | 
			
		||||
          (redisplay))
 | 
			
		||||
      (magit-blame--remove-overlays)))
 | 
			
		||||
  (setq magit-blame-type type))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-visit-other-file ()
 | 
			
		||||
  "Visit another blob related to the current chunk."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (with-slots (prev-rev prev-file orig-line)
 | 
			
		||||
      (magit-current-blame-chunk)
 | 
			
		||||
    (unless prev-rev
 | 
			
		||||
      (user-error "Chunk has no further history"))
 | 
			
		||||
    (magit-with-toplevel
 | 
			
		||||
      (magit-find-file prev-rev prev-file))
 | 
			
		||||
    ;; TODO Adjust line like magit-diff-visit-file.
 | 
			
		||||
    (goto-char (point-min))
 | 
			
		||||
    (forward-line (1- orig-line))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-visit-file ()
 | 
			
		||||
  "Visit the blob related to the current chunk."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (with-slots (orig-rev orig-file orig-line)
 | 
			
		||||
      (magit-current-blame-chunk)
 | 
			
		||||
    (magit-with-toplevel
 | 
			
		||||
      (magit-find-file orig-rev orig-file))
 | 
			
		||||
    (goto-char (point-min))
 | 
			
		||||
    (forward-line (1- orig-line))))
 | 
			
		||||
 | 
			
		||||
(transient-define-suffix magit-blame-quit ()
 | 
			
		||||
  "Turn off Magit-Blame mode.
 | 
			
		||||
If the buffer was created during a recursive blame,
 | 
			
		||||
then also kill the buffer."
 | 
			
		||||
  :if-non-nil 'magit-blame-mode
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-blame-mode -1)
 | 
			
		||||
  (when magit-blame-recursive-p
 | 
			
		||||
    (kill-buffer)))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-next-chunk ()
 | 
			
		||||
  "Move to the next chunk."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (--if-let (next-single-char-property-change (point) 'magit-blame-chunk)
 | 
			
		||||
      (goto-char it)
 | 
			
		||||
    (user-error "No more chunks")))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-previous-chunk ()
 | 
			
		||||
  "Move to the previous chunk."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (--if-let (previous-single-char-property-change (point) 'magit-blame-chunk)
 | 
			
		||||
      (goto-char it)
 | 
			
		||||
    (user-error "No more chunks")))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-next-chunk-same-commit (&optional previous)
 | 
			
		||||
  "Move to the next chunk from the same commit.\n\n(fn)"
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if-let ((rev (oref (magit-current-blame-chunk) orig-rev)))
 | 
			
		||||
      (let ((pos (point)) ov)
 | 
			
		||||
        (save-excursion
 | 
			
		||||
          (while (and (not ov)
 | 
			
		||||
                      (not (= pos (if previous (point-min) (point-max))))
 | 
			
		||||
                      (setq pos (funcall
 | 
			
		||||
                                 (if previous
 | 
			
		||||
                                     'previous-single-char-property-change
 | 
			
		||||
                                   'next-single-char-property-change)
 | 
			
		||||
                                 pos 'magit-blame-chunk)))
 | 
			
		||||
            (--when-let (magit-blame--overlay-at pos)
 | 
			
		||||
              (when (equal (oref (magit-blame-chunk-at pos) orig-rev) rev)
 | 
			
		||||
                (setq ov it)))))
 | 
			
		||||
        (if ov
 | 
			
		||||
            (goto-char (overlay-start ov))
 | 
			
		||||
          (user-error "No more chunks from same commit")))
 | 
			
		||||
    (user-error "This chunk hasn't been blamed yet")))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-previous-chunk-same-commit ()
 | 
			
		||||
  "Move to the previous chunk from the same commit."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-blame-next-chunk-same-commit 'previous-single-char-property-change))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-cycle-style ()
 | 
			
		||||
  "Change how blame information is visualized.
 | 
			
		||||
Cycle through the elements of option `magit-blame-styles'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (setq magit-blame--style
 | 
			
		||||
        (or (cadr (cl-member (car magit-blame--style)
 | 
			
		||||
                             magit-blame-styles :key #'car))
 | 
			
		||||
            (car magit-blame-styles)))
 | 
			
		||||
  (magit-blame--update-margin)
 | 
			
		||||
  (magit-blame--update-overlays))
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-copy-hash ()
 | 
			
		||||
  "Save hash of the current chunk's commit to the kill ring.
 | 
			
		||||
 | 
			
		||||
When the region is active, then save the region's content
 | 
			
		||||
instead of the hash, like `kill-ring-save' would."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if (use-region-p)
 | 
			
		||||
      (call-interactively #'copy-region-as-kill)
 | 
			
		||||
    (kill-new (message "%s" (oref (magit-current-blame-chunk) orig-rev)))))
 | 
			
		||||
 | 
			
		||||
;;; Popup
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-blame "magit-blame" nil t)
 | 
			
		||||
(transient-define-prefix magit-blame ()
 | 
			
		||||
  "Show the commits that added or removed lines in the visited file."
 | 
			
		||||
  :man-page "git-blame"
 | 
			
		||||
  :value '("-w")
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   ("-w" "Ignore whitespace" "-w")
 | 
			
		||||
   ("-r" "Do not treat root commits as boundaries" "--root")
 | 
			
		||||
   (magit-blame:-M)
 | 
			
		||||
   (magit-blame:-C)]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   ("b" "Show commits adding lines" magit-blame-addition)
 | 
			
		||||
   ("r" "Show commits removing lines" magit-blame-removal)
 | 
			
		||||
   ("f" "Show last commits that still have lines" magit-blame-reverse)
 | 
			
		||||
   ("m" "Blame echo" magit-blame-echo)
 | 
			
		||||
   ("q" "Quit blaming" magit-blame-quit)]
 | 
			
		||||
  ["Refresh"
 | 
			
		||||
   :if-non-nil magit-blame-mode
 | 
			
		||||
   ("c" "Cycle style" magit-blame-cycle-style)])
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-arguments ()
 | 
			
		||||
  (transient-args 'magit-blame))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-blame:-M ()
 | 
			
		||||
  :description "Detect lines moved or copied within a file"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :argument "-M"
 | 
			
		||||
  :reader 'transient-read-number-N+)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-blame:-C ()
 | 
			
		||||
  :description "Detect lines moved or copied between files"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :argument "-C"
 | 
			
		||||
  :reader 'transient-read-number-N+)
 | 
			
		||||
 | 
			
		||||
;;; Utilities
 | 
			
		||||
 | 
			
		||||
(defun magit-blame-maybe-update-revision-buffer ()
 | 
			
		||||
  (when-let ((chunk  (magit-current-blame-chunk))
 | 
			
		||||
             (commit (oref chunk orig-rev))
 | 
			
		||||
             (buffer (magit-get-mode-buffer 'magit-revision-mode nil t)))
 | 
			
		||||
    (if magit--update-revision-buffer
 | 
			
		||||
        (setq magit--update-revision-buffer (list commit buffer))
 | 
			
		||||
      (setq magit--update-revision-buffer (list commit buffer))
 | 
			
		||||
      (run-with-idle-timer
 | 
			
		||||
       magit-update-other-window-delay nil
 | 
			
		||||
       (lambda ()
 | 
			
		||||
         (pcase-let ((`(,rev ,buf) magit--update-revision-buffer))
 | 
			
		||||
           (setq magit--update-revision-buffer nil)
 | 
			
		||||
           (when (buffer-live-p buf)
 | 
			
		||||
             (let ((magit-display-buffer-noselect t))
 | 
			
		||||
               (apply #'magit-show-commit rev
 | 
			
		||||
                      (magit-diff-arguments 'magit-revision-mode))))))))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-blame)
 | 
			
		||||
;;; magit-blame.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,203 +0,0 @@
 | 
			
		||||
;;; magit-bookmark.el --- bookmark support for Magit  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Inspired by an earlier implementation by Yuri Khan.
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Support for bookmarks for most Magit buffers.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
(require 'bookmark)
 | 
			
		||||
 | 
			
		||||
;;; Core
 | 
			
		||||
 | 
			
		||||
(defun magit--make-bookmark ()
 | 
			
		||||
  "Create a bookmark for the current Magit buffer.
 | 
			
		||||
Input values are the major-mode's `magit-bookmark-name' method,
 | 
			
		||||
and the buffer-local values of the variables referenced in its
 | 
			
		||||
`magit-bookmark-variables' property."
 | 
			
		||||
  (if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables)
 | 
			
		||||
      (let ((bookmark (bookmark-make-record-default 'no-file)))
 | 
			
		||||
        (bookmark-prop-set bookmark 'handler  'magit--handle-bookmark)
 | 
			
		||||
        (bookmark-prop-set bookmark 'mode     major-mode)
 | 
			
		||||
        (bookmark-prop-set bookmark 'filename (magit-toplevel))
 | 
			
		||||
        (bookmark-prop-set bookmark 'defaults (list (magit-bookmark-name)))
 | 
			
		||||
        (dolist (var (get major-mode 'magit-bookmark-variables))
 | 
			
		||||
          (bookmark-prop-set bookmark var (symbol-value var)))
 | 
			
		||||
        (bookmark-prop-set
 | 
			
		||||
         bookmark 'magit-hidden-sections
 | 
			
		||||
         (--keep (and (oref it hidden)
 | 
			
		||||
                      (cons (oref it type)
 | 
			
		||||
                            (if (derived-mode-p 'magit-stash-mode)
 | 
			
		||||
                                (replace-regexp-in-string
 | 
			
		||||
                                 (regexp-quote magit-buffer-revision)
 | 
			
		||||
                                 magit-buffer-revision-hash
 | 
			
		||||
                                 (oref it value))
 | 
			
		||||
                              (oref it value))))
 | 
			
		||||
                 (oref magit-root-section children)))
 | 
			
		||||
        bookmark)
 | 
			
		||||
    (user-error "Bookmarking is not implemented for %s buffers" major-mode)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit--handle-bookmark (bookmark)
 | 
			
		||||
  "Open a bookmark created by `magit--make-bookmark'.
 | 
			
		||||
Call the `magit-*-setup-buffer' function of the the major-mode
 | 
			
		||||
with the variables' values as arguments, which were recorded by
 | 
			
		||||
`magit--make-bookmark'.  Ignore `magit-display-buffer-function'."
 | 
			
		||||
  (let ((buffer (let ((default-directory (bookmark-get-filename bookmark))
 | 
			
		||||
                      (mode (bookmark-prop-get bookmark 'mode))
 | 
			
		||||
                      (magit-display-buffer-function #'identity)
 | 
			
		||||
                      (magit-display-buffer-noselect t))
 | 
			
		||||
                  (apply (intern (format "%s-setup-buffer"
 | 
			
		||||
                                         (substring (symbol-name mode) 0 -5)))
 | 
			
		||||
                         (--map (bookmark-prop-get bookmark it)
 | 
			
		||||
                                (get mode 'magit-bookmark-variables))))))
 | 
			
		||||
    (set-buffer buffer) ; That is the interface we have to adhere to.
 | 
			
		||||
    (when-let ((hidden (bookmark-prop-get bookmark 'magit-hidden-sections)))
 | 
			
		||||
      (with-current-buffer buffer
 | 
			
		||||
        (dolist (child (oref magit-root-section children))
 | 
			
		||||
          (if (member (cons (oref child type)
 | 
			
		||||
                            (oref child value))
 | 
			
		||||
                      hidden)
 | 
			
		||||
              (magit-section-hide child)
 | 
			
		||||
            (magit-section-show child)))))
 | 
			
		||||
    nil))
 | 
			
		||||
 | 
			
		||||
(cl-defgeneric magit-bookmark-name ()
 | 
			
		||||
  "Return name for bookmark to current buffer."
 | 
			
		||||
  (format "%s%s"
 | 
			
		||||
          (substring (symbol-name major-mode) 0 -5)
 | 
			
		||||
          (if-let ((vars (get major-mode 'magit-bookmark-variables)))
 | 
			
		||||
              (cl-mapcan (lambda (var)
 | 
			
		||||
                           (let ((val (symbol-value var)))
 | 
			
		||||
                             (if (and val (atom val))
 | 
			
		||||
                                 (list val)
 | 
			
		||||
                               val)))
 | 
			
		||||
                         vars)
 | 
			
		||||
            "")))
 | 
			
		||||
 | 
			
		||||
;;; Diff
 | 
			
		||||
;;;; Diff
 | 
			
		||||
 | 
			
		||||
(put 'magit-diff-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-range-hashed
 | 
			
		||||
       magit-buffer-typearg
 | 
			
		||||
       magit-buffer-diff-args
 | 
			
		||||
       magit-buffer-diff-files))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-diff-mode))
 | 
			
		||||
  (format "magit-diff(%s%s)"
 | 
			
		||||
          (pcase (magit-diff-type)
 | 
			
		||||
            (`staged "staged")
 | 
			
		||||
            (`unstaged "unstaged")
 | 
			
		||||
            (`committed magit-buffer-range)
 | 
			
		||||
            (`undefined
 | 
			
		||||
             (delq nil (list magit-buffer-typearg magit-buffer-range-hashed))))
 | 
			
		||||
          (if magit-buffer-diff-files
 | 
			
		||||
              (concat " -- " (mapconcat #'identity magit-buffer-diff-files " "))
 | 
			
		||||
            "")))
 | 
			
		||||
 | 
			
		||||
;;;; Revision
 | 
			
		||||
 | 
			
		||||
(put 'magit-revision-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-revision-hash
 | 
			
		||||
       magit-buffer-diff-args
 | 
			
		||||
       magit-buffer-diff-files))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-revision-mode))
 | 
			
		||||
  (format "magit-revision(%s %s)"
 | 
			
		||||
          (magit-rev-abbrev magit-buffer-revision)
 | 
			
		||||
          (if magit-buffer-diff-files
 | 
			
		||||
              (mapconcat #'identity magit-buffer-diff-files " ")
 | 
			
		||||
            (magit-rev-format "%s" magit-buffer-revision))))
 | 
			
		||||
 | 
			
		||||
;;;; Stash
 | 
			
		||||
 | 
			
		||||
(put 'magit-stash-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-revision-hash
 | 
			
		||||
       magit-buffer-diff-args
 | 
			
		||||
       magit-buffer-diff-files))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-stash-mode))
 | 
			
		||||
  (format "magit-stash(%s %s)"
 | 
			
		||||
          (magit-rev-abbrev magit-buffer-revision)
 | 
			
		||||
          (if magit-buffer-diff-files
 | 
			
		||||
              (mapconcat #'identity magit-buffer-diff-files " ")
 | 
			
		||||
            (magit-rev-format "%s" magit-buffer-revision))))
 | 
			
		||||
 | 
			
		||||
;;; Log
 | 
			
		||||
;;;; Log
 | 
			
		||||
 | 
			
		||||
(put 'magit-log-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-revisions
 | 
			
		||||
       magit-buffer-log-args
 | 
			
		||||
       magit-buffer-log-files))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-log-mode))
 | 
			
		||||
  (format "magit-log(%s%s)"
 | 
			
		||||
          (mapconcat #'identity magit-buffer-revisions " ")
 | 
			
		||||
          (if magit-buffer-log-files
 | 
			
		||||
              (concat " -- " (mapconcat #'identity magit-buffer-log-files " "))
 | 
			
		||||
            "")))
 | 
			
		||||
 | 
			
		||||
;;;; Cherry
 | 
			
		||||
 | 
			
		||||
(put 'magit-cherry-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-refname
 | 
			
		||||
       magit-buffer-upstream))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-cherry-mode))
 | 
			
		||||
  (format "magit-cherry(%s > %s)"
 | 
			
		||||
          magit-buffer-refname
 | 
			
		||||
          magit-buffer-upstream))
 | 
			
		||||
 | 
			
		||||
;;;; Reflog
 | 
			
		||||
 | 
			
		||||
(put 'magit-reflog-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-refname))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-reflog-mode))
 | 
			
		||||
  (format "magit-reflog(%s)" magit-buffer-refname))
 | 
			
		||||
 | 
			
		||||
;;; Misc
 | 
			
		||||
 | 
			
		||||
(put 'magit-status-mode 'magit-bookmark-variables nil)
 | 
			
		||||
 | 
			
		||||
(put 'magit-refs-mode 'magit-bookmark-variables
 | 
			
		||||
     '(magit-buffer-upstream
 | 
			
		||||
       magit-buffer-arguments))
 | 
			
		||||
 | 
			
		||||
(put 'magit-stashes-mode 'magit-bookmark-variables nil)
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-bookmark-name (&context (major-mode magit-stashes-mode))
 | 
			
		||||
  (format "magit-states(%s)" magit-buffer-refname))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-bookmark)
 | 
			
		||||
;;; magit-bookmark.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,893 +0,0 @@
 | 
			
		||||
;;; magit-branch.el --- branch support  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements support for branches.  It defines commands
 | 
			
		||||
;; for creating, checking out, manipulating, and configuring branches.
 | 
			
		||||
;; Commands defined here are mainly concerned with branches as
 | 
			
		||||
;; pointers, commands that deal with what a branch points at, are
 | 
			
		||||
;; defined elsewhere.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
(require 'magit-reset)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-branch-read-upstream-first t
 | 
			
		||||
  "Whether to read upstream before name of new branch when creating a branch.
 | 
			
		||||
 | 
			
		||||
`nil'      Read the branch name first.
 | 
			
		||||
`t'        Read the upstream first.
 | 
			
		||||
`fallback' Read the upstream first, but if it turns out that the chosen
 | 
			
		||||
           value is not a valid upstream (because it cannot be resolved
 | 
			
		||||
           as an existing revision), then treat it as the name of the
 | 
			
		||||
           new branch and continue by reading the upstream next."
 | 
			
		||||
  :package-version '(magit . "2.2.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(choice (const :tag "read branch name first" nil)
 | 
			
		||||
                 (const :tag "read upstream first" t)
 | 
			
		||||
                 (const :tag "read upstream first, with fallback" fallback)))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-branch-prefer-remote-upstream nil
 | 
			
		||||
  "Whether to favor remote upstreams when creating new branches.
 | 
			
		||||
 | 
			
		||||
When a new branch is created, then the branch, commit, or stash
 | 
			
		||||
at point is suggested as the default starting point of the new
 | 
			
		||||
branch, or if there is no such revision at point the current
 | 
			
		||||
branch.  In either case the user may choose another starting
 | 
			
		||||
point.
 | 
			
		||||
 | 
			
		||||
If the chosen starting point is a branch, then it may also be set
 | 
			
		||||
as the upstream of the new branch, depending on the value of the
 | 
			
		||||
Git variable `branch.autoSetupMerge'.  By default this is done
 | 
			
		||||
for remote branches, but not for local branches.
 | 
			
		||||
 | 
			
		||||
You might prefer to always use some remote branch as upstream.
 | 
			
		||||
If the chosen starting point is (1) a local branch, (2) whose
 | 
			
		||||
name matches a member of the value of this option, (3) the
 | 
			
		||||
upstream of that local branch is a remote branch with the same
 | 
			
		||||
name, and (4) that remote branch can be fast-forwarded to the
 | 
			
		||||
local branch, then the chosen branch is used as starting point,
 | 
			
		||||
but its own upstream is used as the upstream of the new branch.
 | 
			
		||||
 | 
			
		||||
Members of this option's value are treated as branch names that
 | 
			
		||||
have to match exactly unless they contain a character that makes
 | 
			
		||||
them invalid as a branch name.  Recommended characters to use
 | 
			
		||||
to trigger interpretation as a regexp are \"*\" and \"^\".  Some
 | 
			
		||||
other characters which you might expect to be invalid, actually
 | 
			
		||||
are not, e.g. \".+$\" are all perfectly valid.  More precisely,
 | 
			
		||||
if `git check-ref-format --branch STRING' exits with a non-zero
 | 
			
		||||
status, then treat STRING as a regexp.
 | 
			
		||||
 | 
			
		||||
Assuming the chosen branch matches these conditions you would end
 | 
			
		||||
up with with e.g.:
 | 
			
		||||
 | 
			
		||||
  feature --upstream--> origin/master
 | 
			
		||||
 | 
			
		||||
instead of
 | 
			
		||||
 | 
			
		||||
  feature --upstream--> master --upstream--> origin/master
 | 
			
		||||
 | 
			
		||||
Which you prefer is a matter of personal preference.  If you do
 | 
			
		||||
prefer the former, then you should add branches such as \"master\",
 | 
			
		||||
\"next\", and \"maint\" to the value of this options."
 | 
			
		||||
  :package-version '(magit . "2.4.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(repeat string))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-branch-adjust-remote-upstream-alist nil
 | 
			
		||||
  "Alist of upstreams to be used when branching from remote branches.
 | 
			
		||||
 | 
			
		||||
When creating a local branch from an ephemeral branch located
 | 
			
		||||
on a remote, e.g. a feature or hotfix branch, then that remote
 | 
			
		||||
branch should usually not be used as the upstream branch, since
 | 
			
		||||
the push-remote already allows accessing it and having both the
 | 
			
		||||
upstream and the push-remote reference the same related branch
 | 
			
		||||
would be wasteful.  Instead a branch like \"maint\" or \"master\"
 | 
			
		||||
should be used as the upstream.
 | 
			
		||||
 | 
			
		||||
This option allows specifying the branch that should be used as
 | 
			
		||||
the upstream when branching certain remote branches.  The value
 | 
			
		||||
is an alist of the form ((UPSTREAM . RULE)...).  The first
 | 
			
		||||
matching element is used, the following elements are ignored.
 | 
			
		||||
 | 
			
		||||
UPSTREAM is the branch to be used as the upstream for branches
 | 
			
		||||
specified by RULE.  It can be a local or a remote branch.
 | 
			
		||||
 | 
			
		||||
RULE can either be a regular expression, matching branches whose
 | 
			
		||||
upstream should be the one specified by UPSTREAM.  Or it can be
 | 
			
		||||
a list of the only branches that should *not* use UPSTREAM; all
 | 
			
		||||
other branches will.  Matching is done after stripping the remote
 | 
			
		||||
part of the name of the branch that is being branched from.
 | 
			
		||||
 | 
			
		||||
If you use a finite set of non-ephemeral branches across all your
 | 
			
		||||
repositories, then you might use something like:
 | 
			
		||||
 | 
			
		||||
  ((\"origin/master\" \"master\" \"next\" \"maint\"))
 | 
			
		||||
 | 
			
		||||
Or if the names of all your ephemeral branches contain a slash,
 | 
			
		||||
at least in some repositories, then a good value could be:
 | 
			
		||||
 | 
			
		||||
  ((\"origin/master\" . \"/\"))
 | 
			
		||||
 | 
			
		||||
Of course you can also fine-tune:
 | 
			
		||||
 | 
			
		||||
  ((\"origin/maint\" . \"\\\\\\=`hotfix/\")
 | 
			
		||||
   (\"origin/master\" . \"\\\\\\=`feature/\"))
 | 
			
		||||
 | 
			
		||||
If you use remote branches as UPSTREAM, then you might also want
 | 
			
		||||
to set `magit-branch-prefer-remote-upstream' to a non-nil value.
 | 
			
		||||
However, I recommend that you use local branches as UPSTREAM."
 | 
			
		||||
  :package-version '(magit . "2.9.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(repeat (cons (string :tag "Use upstream")
 | 
			
		||||
                       (choice :tag "for branches"
 | 
			
		||||
                               (regexp :tag "matching")
 | 
			
		||||
                               (repeat :tag "except"
 | 
			
		||||
                                       (string :tag "branch"))))))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-branch-rename-push-target t
 | 
			
		||||
  "Whether the push-remote setup is preserved when renaming a branch.
 | 
			
		||||
 | 
			
		||||
The command `magit-branch-rename' renames a branch named OLD to
 | 
			
		||||
NEW.  This option controls how much of the push-remote setup is
 | 
			
		||||
preserved when doing so.
 | 
			
		||||
 | 
			
		||||
When nil, then preserve nothing and unset `branch.OLD.pushRemote'.
 | 
			
		||||
 | 
			
		||||
When `local-only', then first set `branch.NEW.pushRemote' to the
 | 
			
		||||
  same value as `branch.OLD.pushRemote', provided the latter is
 | 
			
		||||
  actually set and unless the former already has another value.
 | 
			
		||||
 | 
			
		||||
When t, then rename the branch named OLD on the remote specified
 | 
			
		||||
  by `branch.OLD.pushRemote' to NEW, provided OLD exists on that
 | 
			
		||||
  remote and unless NEW already exists on the remote.
 | 
			
		||||
 | 
			
		||||
When `forge-only' and the `forge' package is available, then
 | 
			
		||||
  behave like `t' if the remote points to a repository on a forge
 | 
			
		||||
  (currently Github or Gitlab), otherwise like `local-only'.
 | 
			
		||||
 | 
			
		||||
Another supported but obsolete value is `github-only'.  It is a
 | 
			
		||||
  misnomer because it now treated as an alias for `forge-only'."
 | 
			
		||||
  :package-version '(magit . "2.90.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(choice
 | 
			
		||||
          (const :tag "Don't preserve push-remote setup" nil)
 | 
			
		||||
          (const :tag "Preserve push-remote setup" local-only)
 | 
			
		||||
          (const :tag "... and rename corresponding branch on remote" t)
 | 
			
		||||
          (const :tag "... but only if remote is on a forge" forge-only)))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-branch-direct-configure t
 | 
			
		||||
  "Whether the command `magit-branch' shows Git variables.
 | 
			
		||||
When set to nil, no variables are displayed by this transient
 | 
			
		||||
command, instead the sub-transient `magit-branch-configure'
 | 
			
		||||
has to be used to view and change branch related variables."
 | 
			
		||||
  :package-version '(magit . "2.7.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-published-branches '("origin/master")
 | 
			
		||||
  "List of branches that are considered to be published."
 | 
			
		||||
  :package-version '(magit . "2.13.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(repeat string))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-branch "magit" nil t)
 | 
			
		||||
(transient-define-prefix magit-branch (branch)
 | 
			
		||||
  "Add, configure or remove a branch."
 | 
			
		||||
  :man-page "git-branch"
 | 
			
		||||
  ["Variables"
 | 
			
		||||
   :if (lambda ()
 | 
			
		||||
         (and magit-branch-direct-configure
 | 
			
		||||
              (oref transient--prefix scope)))
 | 
			
		||||
   ("d" magit-branch.<branch>.description)
 | 
			
		||||
   ("u" magit-branch.<branch>.merge/remote)
 | 
			
		||||
   ("r" magit-branch.<branch>.rebase)
 | 
			
		||||
   ("p" magit-branch.<branch>.pushRemote)]
 | 
			
		||||
  [["Checkout"
 | 
			
		||||
    ("b" "branch/revision"   magit-checkout)
 | 
			
		||||
    ("l" "local branch"      magit-branch-checkout)
 | 
			
		||||
    (6 "o" "new orphan"      magit-branch-orphan)]
 | 
			
		||||
   [""
 | 
			
		||||
    ("c" "new branch"        magit-branch-and-checkout)
 | 
			
		||||
    ("s" "new spin-off"      magit-branch-spinoff)
 | 
			
		||||
    (5 "w" "new worktree"    magit-worktree-checkout)]
 | 
			
		||||
   ["Create"
 | 
			
		||||
    ("n" "new branch"        magit-branch-create)
 | 
			
		||||
    ("S" "new spin-out"      magit-branch-spinout)
 | 
			
		||||
    (5 "W" "new worktree"    magit-worktree-branch)]
 | 
			
		||||
   ["Do"
 | 
			
		||||
    ("C" "configure..."      magit-branch-configure)
 | 
			
		||||
    ("m" "rename"            magit-branch-rename)
 | 
			
		||||
    ("x" "reset"             magit-branch-reset)
 | 
			
		||||
    ("k" "delete"            magit-branch-delete)]
 | 
			
		||||
   [""
 | 
			
		||||
    (7 "h" "shelve"          magit-branch-shelve)
 | 
			
		||||
    (7 "H" "unshelve"        magit-branch-unshelve)]]
 | 
			
		||||
  (interactive (list (magit-get-current-branch)))
 | 
			
		||||
  (transient-setup 'magit-branch nil nil :scope branch))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-checkout (revision)
 | 
			
		||||
  "Checkout REVISION, updating the index and the working tree.
 | 
			
		||||
If REVISION is a local branch, then that becomes the current
 | 
			
		||||
branch.  If it is something else, then `HEAD' becomes detached.
 | 
			
		||||
Checkout fails if the working tree or the staging area contain
 | 
			
		||||
changes.
 | 
			
		||||
\n(git checkout REVISION)."
 | 
			
		||||
  (interactive (list (magit-read-other-branch-or-commit "Checkout")))
 | 
			
		||||
  (when (string-match "\\`heads/\\(.+\\)" revision)
 | 
			
		||||
    (setq revision (match-string 1 revision)))
 | 
			
		||||
  (magit-run-git "checkout" revision))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-create (branch start-point)
 | 
			
		||||
  "Create BRANCH at branch or revision START-POINT."
 | 
			
		||||
  (interactive (magit-branch-read-args "Create branch"))
 | 
			
		||||
  (magit-call-git "branch" branch start-point)
 | 
			
		||||
  (magit-branch-maybe-adjust-upstream branch start-point)
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-and-checkout (branch start-point)
 | 
			
		||||
  "Create and checkout BRANCH at branch or revision START-POINT."
 | 
			
		||||
  (interactive (magit-branch-read-args "Create and checkout branch"))
 | 
			
		||||
  (if (string-match-p "^stash@{[0-9]+}$" start-point)
 | 
			
		||||
      (magit-run-git "stash" "branch" branch start-point)
 | 
			
		||||
    (magit-call-git "checkout" "-b" branch start-point)
 | 
			
		||||
    (magit-branch-maybe-adjust-upstream branch start-point)
 | 
			
		||||
    (magit-refresh)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-or-checkout (arg &optional start-point)
 | 
			
		||||
  "Hybrid between `magit-checkout' and `magit-branch-and-checkout'.
 | 
			
		||||
 | 
			
		||||
Ask the user for an existing branch or revision.  If the user
 | 
			
		||||
input actually can be resolved as a branch or revision, then
 | 
			
		||||
check that out, just like `magit-checkout' would.
 | 
			
		||||
 | 
			
		||||
Otherwise create and checkout a new branch using the input as
 | 
			
		||||
its name.  Before doing so read the starting-point for the new
 | 
			
		||||
branch.  This is similar to what `magit-branch-and-checkout'
 | 
			
		||||
does."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((arg (magit-read-other-branch-or-commit "Checkout")))
 | 
			
		||||
     (list arg
 | 
			
		||||
           (and (not (magit-commit-p arg))
 | 
			
		||||
                (magit-read-starting-point "Create and checkout branch" arg)))))
 | 
			
		||||
  (when (string-match "\\`heads/\\(.+\\)" arg)
 | 
			
		||||
    (setq arg (match-string 1 arg)))
 | 
			
		||||
  (if start-point
 | 
			
		||||
      (magit-branch-and-checkout arg start-point)
 | 
			
		||||
    (magit-checkout arg)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-checkout (branch &optional start-point)
 | 
			
		||||
  "Checkout an existing or new local branch.
 | 
			
		||||
 | 
			
		||||
Read a branch name from the user offering all local branches and
 | 
			
		||||
a subset of remote branches as candidates.  Omit remote branches
 | 
			
		||||
for which a local branch by the same name exists from the list
 | 
			
		||||
of candidates.  The user can also enter a completely new branch
 | 
			
		||||
name.
 | 
			
		||||
 | 
			
		||||
- If the user selects an existing local branch, then check that
 | 
			
		||||
  out.
 | 
			
		||||
 | 
			
		||||
- If the user selects a remote branch, then create and checkout
 | 
			
		||||
  a new local branch with the same name.  Configure the selected
 | 
			
		||||
  remote branch as push target.
 | 
			
		||||
 | 
			
		||||
- If the user enters a new branch name, then create and check
 | 
			
		||||
  that out, after also reading the starting-point from the user.
 | 
			
		||||
 | 
			
		||||
In the latter two cases the upstream is also set.  Whether it is
 | 
			
		||||
set to the chosen START-POINT or something else depends on the
 | 
			
		||||
value of `magit-branch-adjust-remote-upstream-alist', just like
 | 
			
		||||
when using `magit-branch-and-checkout'."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let* ((current (magit-get-current-branch))
 | 
			
		||||
          (local   (magit-list-local-branch-names))
 | 
			
		||||
          (remote  (--filter (and (string-match "[^/]+/" it)
 | 
			
		||||
                                  (not (member (substring it (match-end 0))
 | 
			
		||||
                                               (cons "HEAD" local))))
 | 
			
		||||
                             (magit-list-remote-branch-names)))
 | 
			
		||||
          (choices (nconc (delete current local) remote))
 | 
			
		||||
          (atpoint (magit-branch-at-point))
 | 
			
		||||
          (choice  (magit-completing-read
 | 
			
		||||
                    "Checkout branch" choices
 | 
			
		||||
                    nil nil nil 'magit-revision-history
 | 
			
		||||
                    (or (car (member atpoint choices))
 | 
			
		||||
                        (and atpoint
 | 
			
		||||
                             (car (member (and (string-match "[^/]+/" atpoint)
 | 
			
		||||
                                               (substring atpoint (match-end 0)))
 | 
			
		||||
                                          choices)))))))
 | 
			
		||||
     (cond ((member choice remote)
 | 
			
		||||
            (list (and (string-match "[^/]+/" choice)
 | 
			
		||||
                       (substring choice (match-end 0)))
 | 
			
		||||
                  choice))
 | 
			
		||||
           ((member choice local)
 | 
			
		||||
            (list choice))
 | 
			
		||||
           (t
 | 
			
		||||
            (list choice (magit-read-starting-point "Create" choice))))))
 | 
			
		||||
  (if (not start-point)
 | 
			
		||||
      (magit-checkout branch)
 | 
			
		||||
    (when (magit-anything-modified-p t)
 | 
			
		||||
      (user-error "Cannot checkout when there are uncommitted changes"))
 | 
			
		||||
    (magit-branch-and-checkout branch start-point)
 | 
			
		||||
    (when (magit-remote-branch-p start-point)
 | 
			
		||||
      (pcase-let ((`(,remote . ,remote-branch)
 | 
			
		||||
                   (magit-split-branch-name start-point)))
 | 
			
		||||
        (when (and (equal branch remote-branch)
 | 
			
		||||
                   (not (equal remote (magit-get "remote.pushDefault"))))
 | 
			
		||||
          (magit-set remote "branch" branch "pushRemote"))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-branch-maybe-adjust-upstream (branch start-point)
 | 
			
		||||
  (--when-let
 | 
			
		||||
      (or (and (magit-get-upstream-branch branch)
 | 
			
		||||
               (magit-get-indirect-upstream-branch start-point))
 | 
			
		||||
          (and (magit-remote-branch-p start-point)
 | 
			
		||||
               (let ((name (cdr (magit-split-branch-name start-point))))
 | 
			
		||||
                 (car (--first (if (listp (cdr it))
 | 
			
		||||
                                   (not (member name (cdr it)))
 | 
			
		||||
                                 (string-match-p (cdr it) name))
 | 
			
		||||
                               magit-branch-adjust-remote-upstream-alist)))))
 | 
			
		||||
    (magit-call-git "branch" (concat "--set-upstream-to=" it) branch)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-orphan (branch start-point)
 | 
			
		||||
  "Create and checkout an orphan BRANCH with contents from revision START-POINT."
 | 
			
		||||
  (interactive (magit-branch-read-args "Create and checkout orphan branch"))
 | 
			
		||||
  (magit-run-git "checkout" "--orphan" branch start-point))
 | 
			
		||||
 | 
			
		||||
(defun magit-branch-read-args (prompt &optional default-start)
 | 
			
		||||
  (if magit-branch-read-upstream-first
 | 
			
		||||
      (let ((choice (magit-read-starting-point prompt nil default-start)))
 | 
			
		||||
        (if (magit-rev-verify choice)
 | 
			
		||||
            (list (magit-read-string-ns
 | 
			
		||||
                   (if magit-completing-read--silent-default
 | 
			
		||||
                       (format "%s (starting at `%s')" prompt choice)
 | 
			
		||||
                     "Name for new branch")
 | 
			
		||||
                   (let ((def (mapconcat #'identity
 | 
			
		||||
                                         (cdr (split-string choice "/"))
 | 
			
		||||
                                         "/")))
 | 
			
		||||
                     (and (member choice (magit-list-remote-branch-names))
 | 
			
		||||
                          (not (member def (magit-list-local-branch-names)))
 | 
			
		||||
                          def)))
 | 
			
		||||
                  choice)
 | 
			
		||||
          (if (eq magit-branch-read-upstream-first 'fallback)
 | 
			
		||||
              (list choice
 | 
			
		||||
                    (magit-read-starting-point prompt choice default-start))
 | 
			
		||||
            (user-error "Not a valid starting-point: %s" choice))))
 | 
			
		||||
    (let ((branch (magit-read-string-ns (concat prompt " named"))))
 | 
			
		||||
      (list branch (magit-read-starting-point prompt branch default-start)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-spinout (branch &optional from)
 | 
			
		||||
  "Create new branch from the unpushed commits.
 | 
			
		||||
Like `magit-branch-spinoff' but remain on the current branch.
 | 
			
		||||
If there are any uncommitted changes, then behave exactly like
 | 
			
		||||
`magit-branch-spinoff'."
 | 
			
		||||
  (interactive (list (magit-read-string-ns "Spin out branch")
 | 
			
		||||
                     (car (last (magit-region-values 'commit)))))
 | 
			
		||||
  (magit--branch-spinoff branch from nil))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-spinoff (branch &optional from)
 | 
			
		||||
  "Create new branch from the unpushed commits.
 | 
			
		||||
 | 
			
		||||
Create and checkout a new branch starting at and tracking the
 | 
			
		||||
current branch.  That branch in turn is reset to the last commit
 | 
			
		||||
it shares with its upstream.  If the current branch has no
 | 
			
		||||
upstream or no unpushed commits, then the new branch is created
 | 
			
		||||
anyway and the previously current branch is not touched.
 | 
			
		||||
 | 
			
		||||
This is useful to create a feature branch after work has already
 | 
			
		||||
began on the old branch (likely but not necessarily \"master\").
 | 
			
		||||
 | 
			
		||||
If the current branch is a member of the value of option
 | 
			
		||||
`magit-branch-prefer-remote-upstream' (which see), then the
 | 
			
		||||
current branch will be used as the starting point as usual, but
 | 
			
		||||
the upstream of the starting-point may be used as the upstream
 | 
			
		||||
of the new branch, instead of the starting-point itself.
 | 
			
		||||
 | 
			
		||||
If optional FROM is non-nil, then the source branch is reset
 | 
			
		||||
to `FROM~', instead of to the last commit it shares with its
 | 
			
		||||
upstream.  Interactively, FROM is only ever non-nil, if the
 | 
			
		||||
region selects some commits, and among those commits, FROM is
 | 
			
		||||
the commit that is the fewest commits ahead of the source
 | 
			
		||||
branch.
 | 
			
		||||
 | 
			
		||||
The commit at the other end of the selection actually does not
 | 
			
		||||
matter, all commits between FROM and `HEAD' are moved to the new
 | 
			
		||||
branch.  If FROM is not reachable from `HEAD' or is reachable
 | 
			
		||||
from the source branch's upstream, then an error is raised."
 | 
			
		||||
  (interactive (list (magit-read-string-ns "Spin off branch")
 | 
			
		||||
                     (car (last (magit-region-values 'commit)))))
 | 
			
		||||
  (magit--branch-spinoff branch from t))
 | 
			
		||||
 | 
			
		||||
(defun magit--branch-spinoff (branch from checkout)
 | 
			
		||||
  (when (magit-branch-p branch)
 | 
			
		||||
    (user-error "Cannot spin off %s.  It already exists" branch))
 | 
			
		||||
  (when (and (not checkout)
 | 
			
		||||
             (magit-anything-modified-p))
 | 
			
		||||
    (message "Staying on HEAD due to uncommitted changes")
 | 
			
		||||
    (setq checkout t))
 | 
			
		||||
  (if-let ((current (magit-get-current-branch)))
 | 
			
		||||
      (let ((tracked (magit-get-upstream-branch current))
 | 
			
		||||
            base)
 | 
			
		||||
        (when from
 | 
			
		||||
          (unless (magit-rev-ancestor-p from current)
 | 
			
		||||
            (user-error "Cannot spin off %s.  %s is not reachable from %s"
 | 
			
		||||
                        branch from current))
 | 
			
		||||
          (when (and tracked
 | 
			
		||||
                     (magit-rev-ancestor-p from tracked))
 | 
			
		||||
            (user-error "Cannot spin off %s.  %s is ancestor of upstream %s"
 | 
			
		||||
                        branch from tracked)))
 | 
			
		||||
        (let ((magit-process-raise-error t))
 | 
			
		||||
          (if checkout
 | 
			
		||||
              (magit-call-git "checkout" "-b" branch current)
 | 
			
		||||
            (magit-call-git "branch" branch current)))
 | 
			
		||||
        (--when-let (magit-get-indirect-upstream-branch current)
 | 
			
		||||
          (magit-call-git "branch" "--set-upstream-to" it branch))
 | 
			
		||||
        (when (and tracked
 | 
			
		||||
                   (setq base
 | 
			
		||||
                         (if from
 | 
			
		||||
                             (concat from "^")
 | 
			
		||||
                           (magit-git-string "merge-base" current tracked)))
 | 
			
		||||
                   (not (magit-rev-eq base current)))
 | 
			
		||||
          (if checkout
 | 
			
		||||
              (magit-call-git "update-ref" "-m"
 | 
			
		||||
                              (format "reset: moving to %s" base)
 | 
			
		||||
                              (concat "refs/heads/" current) base)
 | 
			
		||||
            (magit-call-git "reset" "--hard" base))))
 | 
			
		||||
    (if checkout
 | 
			
		||||
        (magit-call-git "checkout" "-b" branch)
 | 
			
		||||
      (magit-call-git "branch" branch)))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-reset (branch to &optional set-upstream)
 | 
			
		||||
  "Reset a branch to the tip of another branch or any other commit.
 | 
			
		||||
 | 
			
		||||
When the branch being reset is the current branch, then do a
 | 
			
		||||
hard reset.  If there are any uncommitted changes, then the user
 | 
			
		||||
has to confirm the reset because those changes would be lost.
 | 
			
		||||
 | 
			
		||||
This is useful when you have started work on a feature branch but
 | 
			
		||||
realize it's all crap and want to start over.
 | 
			
		||||
 | 
			
		||||
When resetting to another branch and a prefix argument is used,
 | 
			
		||||
then also set the target branch as the upstream of the branch
 | 
			
		||||
that is being reset."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let* ((atpoint (magit-local-branch-at-point))
 | 
			
		||||
          (branch  (magit-read-local-branch "Reset branch" atpoint)))
 | 
			
		||||
     (list branch
 | 
			
		||||
           (magit-completing-read (format "Reset %s to" branch)
 | 
			
		||||
                                  (delete branch (magit-list-branch-names))
 | 
			
		||||
                                  nil nil nil 'magit-revision-history
 | 
			
		||||
                                  (or (and (not (equal branch atpoint)) atpoint)
 | 
			
		||||
                                      (magit-get-upstream-branch branch)))
 | 
			
		||||
           current-prefix-arg)))
 | 
			
		||||
  (let ((inhibit-magit-refresh t))
 | 
			
		||||
    (if (equal branch (magit-get-current-branch))
 | 
			
		||||
        (if (and (magit-anything-modified-p)
 | 
			
		||||
                 (not (yes-or-no-p
 | 
			
		||||
                       "Uncommitted changes will be lost.  Proceed? ")))
 | 
			
		||||
            (user-error "Abort")
 | 
			
		||||
          (magit-reset-hard to))
 | 
			
		||||
      (magit-call-git "update-ref"
 | 
			
		||||
                      "-m" (format "reset: moving to %s" to)
 | 
			
		||||
                      (magit-git-string "rev-parse" "--symbolic-full-name"
 | 
			
		||||
                                        branch)
 | 
			
		||||
                      to))
 | 
			
		||||
    (when (and set-upstream (magit-branch-p to))
 | 
			
		||||
      (magit-set-upstream-branch branch to)
 | 
			
		||||
      (magit-branch-maybe-adjust-upstream branch to)))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
(defvar magit-branch-delete-never-verify nil
 | 
			
		||||
  "Whether `magit-branch-delete' always pushes with \"--no-verify\".")
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-delete (branches &optional force)
 | 
			
		||||
  "Delete one or multiple branches.
 | 
			
		||||
If the region marks multiple branches, then offer to delete
 | 
			
		||||
those, otherwise prompt for a single branch to be deleted,
 | 
			
		||||
defaulting to the branch at point."
 | 
			
		||||
  ;; One would expect this to be a command as simple as, for example,
 | 
			
		||||
  ;; `magit-branch-rename'; but it turns out everyone wants to squeeze
 | 
			
		||||
  ;; a bit of extra functionality into this one, including myself.
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((branches (magit-region-values 'branch t))
 | 
			
		||||
         (force current-prefix-arg))
 | 
			
		||||
     (if (> (length branches) 1)
 | 
			
		||||
         (magit-confirm t nil "Delete %i branches" nil branches)
 | 
			
		||||
       (setq branches
 | 
			
		||||
             (list (magit-read-branch-prefer-other
 | 
			
		||||
                    (if force "Force delete branch" "Delete branch")))))
 | 
			
		||||
     (unless force
 | 
			
		||||
       (when-let ((unmerged (-remove #'magit-branch-merged-p branches)))
 | 
			
		||||
         (if (magit-confirm 'delete-unmerged-branch
 | 
			
		||||
               "Delete unmerged branch %s"
 | 
			
		||||
               "Delete %i unmerged branches"
 | 
			
		||||
               'noabort unmerged)
 | 
			
		||||
             (setq force branches)
 | 
			
		||||
           (or (setq branches (-difference branches unmerged))
 | 
			
		||||
               (user-error "Abort")))))
 | 
			
		||||
     (list branches force)))
 | 
			
		||||
  (let* ((refs (mapcar #'magit-ref-fullname branches))
 | 
			
		||||
         (ambiguous (--remove it refs)))
 | 
			
		||||
    (when ambiguous
 | 
			
		||||
      (user-error
 | 
			
		||||
       "%s ambiguous.  Please cleanup using git directly."
 | 
			
		||||
       (let ((len (length ambiguous)))
 | 
			
		||||
         (cond
 | 
			
		||||
          ((= len 1)
 | 
			
		||||
           (format "%s is" (-first #'magit-ref-ambiguous-p branches)))
 | 
			
		||||
          ((= len (length refs))
 | 
			
		||||
           (format "These %s names are" len))
 | 
			
		||||
          (t
 | 
			
		||||
           (format "%s of these names are" len))))))
 | 
			
		||||
    (cond
 | 
			
		||||
     ((string-match "^refs/remotes/\\([^/]+\\)" (car refs))
 | 
			
		||||
      (let* ((remote (match-string 1 (car refs)))
 | 
			
		||||
             (offset (1+ (length remote))))
 | 
			
		||||
        ;; Assume the branches actually still exists on the remote.
 | 
			
		||||
        (magit-run-git-async
 | 
			
		||||
         "push"
 | 
			
		||||
         (and (or force magit-branch-delete-never-verify) "--no-verify")
 | 
			
		||||
         remote
 | 
			
		||||
         (--map (concat ":" (substring it offset)) branches))
 | 
			
		||||
        ;; If that is not the case, then this deletes the tracking branches.
 | 
			
		||||
        (set-process-sentinel
 | 
			
		||||
         magit-this-process
 | 
			
		||||
         (apply-partially 'magit-delete-remote-branch-sentinel remote refs))))
 | 
			
		||||
     ((> (length branches) 1)
 | 
			
		||||
      (setq branches (delete (magit-get-current-branch) branches))
 | 
			
		||||
      (mapc 'magit-branch-maybe-delete-pr-remote branches)
 | 
			
		||||
      (mapc 'magit-branch-unset-pushRemote branches)
 | 
			
		||||
      (magit-run-git "branch" (if force "-D" "-d") branches))
 | 
			
		||||
     (t ; And now for something completely different.
 | 
			
		||||
      (let* ((branch (car branches))
 | 
			
		||||
             (prompt (format "Branch %s is checked out.  " branch)))
 | 
			
		||||
        (when (equal branch (magit-get-current-branch))
 | 
			
		||||
          (pcase (if (or (equal branch "master")
 | 
			
		||||
                         (not (magit-rev-verify "master")))
 | 
			
		||||
                     (magit-read-char-case prompt nil
 | 
			
		||||
                       (?d "[d]etach HEAD & delete" 'detach)
 | 
			
		||||
                       (?a "[a]bort"                'abort))
 | 
			
		||||
                   (magit-read-char-case prompt nil
 | 
			
		||||
                     (?d "[d]etach HEAD & delete"     'detach)
 | 
			
		||||
                     (?c "[c]heckout master & delete" 'master)
 | 
			
		||||
                     (?a "[a]bort"                    'abort)))
 | 
			
		||||
            (`detach (unless (or (equal force '(4))
 | 
			
		||||
                                 (member branch force)
 | 
			
		||||
                                 (magit-branch-merged-p branch t))
 | 
			
		||||
                       (magit-confirm 'delete-unmerged-branch
 | 
			
		||||
                         "Delete unmerged branch %s" ""
 | 
			
		||||
                         nil (list branch)))
 | 
			
		||||
                     (magit-call-git "checkout" "--detach"))
 | 
			
		||||
            (`master (unless (or (equal force '(4))
 | 
			
		||||
                                 (member branch force)
 | 
			
		||||
                                 (magit-branch-merged-p branch "master"))
 | 
			
		||||
                       (magit-confirm 'delete-unmerged-branch
 | 
			
		||||
                         "Delete unmerged branch %s" ""
 | 
			
		||||
                         nil (list branch)))
 | 
			
		||||
                     (magit-call-git "checkout" "master"))
 | 
			
		||||
            (`abort  (user-error "Abort")))
 | 
			
		||||
          (setq force t))
 | 
			
		||||
        (magit-branch-maybe-delete-pr-remote branch)
 | 
			
		||||
        (magit-branch-unset-pushRemote branch)
 | 
			
		||||
        (magit-run-git "branch" (if force "-D" "-d") branch))))))
 | 
			
		||||
 | 
			
		||||
(put 'magit-branch-delete 'interactive-only t)
 | 
			
		||||
 | 
			
		||||
(defun magit-branch-maybe-delete-pr-remote (branch)
 | 
			
		||||
  (when-let ((remote (magit-get "branch" branch "pullRequestRemote")))
 | 
			
		||||
    (let* ((variable (format "remote.%s.fetch" remote))
 | 
			
		||||
           (refspecs (magit-get-all variable)))
 | 
			
		||||
      (unless (member (format "+refs/heads/*:refs/remotes/%s/*" remote)
 | 
			
		||||
                      refspecs)
 | 
			
		||||
        (let ((refspec
 | 
			
		||||
               (if (equal (magit-get "branch" branch "pushRemote") remote)
 | 
			
		||||
                   (format "+refs/heads/%s:refs/remotes/%s/%s"
 | 
			
		||||
                           branch remote branch)
 | 
			
		||||
                 (let ((merge (magit-get "branch" branch "merge")))
 | 
			
		||||
                   (and merge
 | 
			
		||||
                        (string-prefix-p "refs/heads/" merge)
 | 
			
		||||
                        (setq merge (substring merge 11))
 | 
			
		||||
                        (format "+refs/heads/%s:refs/remotes/%s/%s"
 | 
			
		||||
                                merge remote merge))))))
 | 
			
		||||
          (when (member refspec refspecs)
 | 
			
		||||
            (if (and (= (length refspecs) 1)
 | 
			
		||||
                     (magit-confirm 'delete-pr-remote
 | 
			
		||||
                       (format "Also delete remote %s (%s)" remote
 | 
			
		||||
                               "no pull-request branch remains")
 | 
			
		||||
                       nil t))
 | 
			
		||||
                (magit-call-git "remote" "rm" remote)
 | 
			
		||||
              (magit-call-git "config" "--unset-all" variable
 | 
			
		||||
                              (format "^%s$" (regexp-quote refspec))))))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-branch-unset-pushRemote (branch)
 | 
			
		||||
  (magit-set nil "branch" branch "pushRemote"))
 | 
			
		||||
 | 
			
		||||
(defun magit-delete-remote-branch-sentinel (remote refs process event)
 | 
			
		||||
  (when (memq (process-status process) '(exit signal))
 | 
			
		||||
    (if (= (process-exit-status process) 1)
 | 
			
		||||
        (if-let ((on-remote (--map (concat "refs/remotes/" remote "/" it)
 | 
			
		||||
                                   (magit-remote-list-branches remote)))
 | 
			
		||||
                 (rest (--filter (and (not (member it on-remote))
 | 
			
		||||
                                      (magit-ref-exists-p it))
 | 
			
		||||
                                 refs)))
 | 
			
		||||
            (progn
 | 
			
		||||
              (process-put process 'inhibit-refresh t)
 | 
			
		||||
              (magit-process-sentinel process event)
 | 
			
		||||
              (setq magit-this-error nil)
 | 
			
		||||
              (message "Some remote branches no longer exist.  %s"
 | 
			
		||||
                       "Deleting just the local tracking refs instead...")
 | 
			
		||||
              (dolist (ref rest)
 | 
			
		||||
                (magit-call-git "update-ref" "-d" ref))
 | 
			
		||||
              (magit-refresh)
 | 
			
		||||
              (message "Deleting local remote-tracking refs...done"))
 | 
			
		||||
          (magit-process-sentinel process event))
 | 
			
		||||
      (magit-process-sentinel process event))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-rename (old new &optional force)
 | 
			
		||||
  "Rename the branch named OLD to NEW.
 | 
			
		||||
 | 
			
		||||
With a prefix argument FORCE, rename even if a branch named NEW
 | 
			
		||||
already exists.
 | 
			
		||||
 | 
			
		||||
If `branch.OLD.pushRemote' is set, then unset it.  Depending on
 | 
			
		||||
the value of `magit-branch-rename-push-target' (which see) maybe
 | 
			
		||||
set `branch.NEW.pushRemote' and maybe rename the push-target on
 | 
			
		||||
the remote."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((branch (magit-read-local-branch "Rename branch")))
 | 
			
		||||
     (list branch
 | 
			
		||||
           (magit-read-string-ns (format "Rename branch '%s' to" branch)
 | 
			
		||||
                                 nil 'magit-revision-history)
 | 
			
		||||
           current-prefix-arg)))
 | 
			
		||||
  (when (string-match "\\`heads/\\(.+\\)" old)
 | 
			
		||||
    (setq old (match-string 1 old)))
 | 
			
		||||
  (when (equal old new)
 | 
			
		||||
    (user-error "Old and new branch names are the same"))
 | 
			
		||||
  (magit-call-git "branch" (if force "-M" "-m") old new)
 | 
			
		||||
  (when magit-branch-rename-push-target
 | 
			
		||||
    (let ((remote (magit-get-push-remote old))
 | 
			
		||||
          (old-specific (magit-get "branch" old "pushRemote"))
 | 
			
		||||
          (new-specific (magit-get "branch" new "pushRemote")))
 | 
			
		||||
      (when (and old-specific (or force (not new-specific)))
 | 
			
		||||
        ;; Keep the target setting branch specific, even if that is
 | 
			
		||||
        ;; redundant.  But if a branch by the same name existed before
 | 
			
		||||
        ;; and the rename isn't forced, then do not change a leftover
 | 
			
		||||
        ;; setting.  Such a leftover setting may or may not conform to
 | 
			
		||||
        ;; what we expect here...
 | 
			
		||||
        (magit-set old-specific "branch" new "pushRemote"))
 | 
			
		||||
      (when (and (equal (magit-get-push-remote new) remote)
 | 
			
		||||
                 ;; ...and if it does not, then we must abort.
 | 
			
		||||
                 (not (eq magit-branch-rename-push-target 'local-only))
 | 
			
		||||
                 (or (not (memq magit-branch-rename-push-target
 | 
			
		||||
                                '(forge-only github-only)))
 | 
			
		||||
                     (and (require (quote forge) nil t)
 | 
			
		||||
                          (fboundp 'forge--forge-remote-p)
 | 
			
		||||
                          (forge--forge-remote-p remote))))
 | 
			
		||||
        (let ((old-target (magit-get-push-branch old t))
 | 
			
		||||
              (new-target (magit-get-push-branch new t))
 | 
			
		||||
              (remote (magit-get-push-remote new)))
 | 
			
		||||
          (when (and old-target
 | 
			
		||||
                     (not new-target)
 | 
			
		||||
                     (magit-y-or-n-p (format "Also rename %S to %S on \"%s\""
 | 
			
		||||
                                             old new remote)))
 | 
			
		||||
            ;; Rename on (i.e. within) the remote, but only if the
 | 
			
		||||
            ;; destination ref doesn't exist yet.  If that ref already
 | 
			
		||||
            ;; exists, then it probably is of some value and we better
 | 
			
		||||
            ;; not touch it.  Ignore what the local ref points at,
 | 
			
		||||
            ;; i.e. if the local and the remote ref didn't point at
 | 
			
		||||
            ;; the same commit before the rename then keep it that way.
 | 
			
		||||
            (magit-call-git "push" "-v" remote
 | 
			
		||||
                            (format "%s:refs/heads/%s" old-target new)
 | 
			
		||||
                            (format ":refs/heads/%s" old)))))))
 | 
			
		||||
  (magit-branch-unset-pushRemote old)
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-shelve (branch)
 | 
			
		||||
  "Shelve a BRANCH.
 | 
			
		||||
Rename \"refs/heads/BRANCH\" to \"refs/shelved/BRANCH\",
 | 
			
		||||
and also rename the respective reflog file."
 | 
			
		||||
  (interactive (list (magit-read-other-local-branch "Shelve branch")))
 | 
			
		||||
  (let ((old (concat "refs/heads/"   branch))
 | 
			
		||||
        (new (concat "refs/shelved/" branch)))
 | 
			
		||||
    (magit-git "update-ref" new old "")
 | 
			
		||||
    (magit--rename-reflog-file old new)
 | 
			
		||||
    (magit-branch-unset-pushRemote branch)
 | 
			
		||||
    (magit-run-git "branch" "-D" branch)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-branch-unshelve (branch)
 | 
			
		||||
  "Unshelve a BRANCH
 | 
			
		||||
Rename \"refs/shelved/BRANCH\" to \"refs/heads/BRANCH\",
 | 
			
		||||
and also rename the respective reflog file."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-completing-read
 | 
			
		||||
          "Unshelve branch"
 | 
			
		||||
          (--map (substring it 8)
 | 
			
		||||
                 (magit-list-refnames "refs/shelved"))
 | 
			
		||||
          nil t)))
 | 
			
		||||
  (let ((old (concat "refs/shelved/" branch))
 | 
			
		||||
        (new (concat "refs/heads/"   branch)))
 | 
			
		||||
    (magit-git "update-ref" new old "")
 | 
			
		||||
    (magit--rename-reflog-file old new)
 | 
			
		||||
    (magit-run-git "update-ref" "-d" old)))
 | 
			
		||||
 | 
			
		||||
(defun magit--rename-reflog-file (old new)
 | 
			
		||||
  (let ((old (magit-git-dir (concat "logs/" old)))
 | 
			
		||||
        (new (magit-git-dir (concat "logs/" new))))
 | 
			
		||||
    (when (file-exists-p old)
 | 
			
		||||
      (make-directory (file-name-directory new) t)
 | 
			
		||||
      (rename-file old new t))))
 | 
			
		||||
 | 
			
		||||
;;; Configure
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-branch-configure "magit-branch" nil t)
 | 
			
		||||
(transient-define-prefix magit-branch-configure (branch)
 | 
			
		||||
  "Configure a branch."
 | 
			
		||||
  :man-page "git-branch"
 | 
			
		||||
  [:description
 | 
			
		||||
   (lambda ()
 | 
			
		||||
     (concat
 | 
			
		||||
      (propertize "Configure " 'face 'transient-heading)
 | 
			
		||||
      (propertize (oref transient--prefix scope) 'face 'magit-branch-local)))
 | 
			
		||||
   ("d"   magit-branch.<branch>.description)
 | 
			
		||||
   ("u"   magit-branch.<branch>.merge/remote)
 | 
			
		||||
   ("r"   magit-branch.<branch>.rebase)
 | 
			
		||||
   ("p"   magit-branch.<branch>.pushRemote)]
 | 
			
		||||
  ["Configure repository defaults"
 | 
			
		||||
   ("R" magit-pull.rebase)
 | 
			
		||||
   ("P" magit-remote.pushDefault)]
 | 
			
		||||
  ["Configure branch creation"
 | 
			
		||||
   ("a m" magit-branch.autoSetupMerge)
 | 
			
		||||
   ("a r" magit-branch.autoSetupRebase)]
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (or (and (not current-prefix-arg)
 | 
			
		||||
                  (not (and magit-branch-direct-configure
 | 
			
		||||
                            (eq transient-current-command 'magit-branch)))
 | 
			
		||||
                  (magit-get-current-branch))
 | 
			
		||||
             (magit--read-branch-scope))))
 | 
			
		||||
  (transient-setup 'magit-branch-configure nil nil :scope branch))
 | 
			
		||||
 | 
			
		||||
(defun magit--read-branch-scope (&optional obj)
 | 
			
		||||
  (magit-read-local-branch
 | 
			
		||||
   (if obj
 | 
			
		||||
       (format "Set %s for branch"
 | 
			
		||||
               (format (oref obj variable) "<name>"))
 | 
			
		||||
     "Configure branch")))
 | 
			
		||||
 | 
			
		||||
(transient-define-suffix magit-branch.<branch>.description (branch)
 | 
			
		||||
  "Edit the description of BRANCH."
 | 
			
		||||
  :class 'magit--git-variable
 | 
			
		||||
  :transient nil
 | 
			
		||||
  :variable "branch.%s.description"
 | 
			
		||||
  (interactive (list (oref transient-current-prefix scope)))
 | 
			
		||||
  (magit-run-git-with-editor "branch" "--edit-description" branch))
 | 
			
		||||
 | 
			
		||||
(add-hook 'find-file-hook 'magit-branch-description-check-buffers)
 | 
			
		||||
 | 
			
		||||
(defun magit-branch-description-check-buffers ()
 | 
			
		||||
  (and buffer-file-name
 | 
			
		||||
       (string-match-p "/\\(BRANCH\\|EDIT\\)_DESCRIPTION\\'" buffer-file-name)))
 | 
			
		||||
 | 
			
		||||
(defclass magit--git-branch:upstream (magit--git-variable)
 | 
			
		||||
  ((format :initform " %k %m %M\n   %r %R")))
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-branch.<branch>.merge/remote ()
 | 
			
		||||
  :class 'magit--git-branch:upstream)
 | 
			
		||||
 | 
			
		||||
(cl-defmethod transient-init-value ((obj magit--git-branch:upstream))
 | 
			
		||||
  (when-let ((branch (oref transient--prefix scope))
 | 
			
		||||
             (remote (magit-get "branch" branch "remote"))
 | 
			
		||||
             (merge  (magit-get "branch" branch "merge")))
 | 
			
		||||
    (oset obj value (list remote merge))))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod transient-infix-read ((obj magit--git-branch:upstream))
 | 
			
		||||
  (if (oref obj value)
 | 
			
		||||
      (oset obj value nil)
 | 
			
		||||
    (magit-read-upstream-branch (oref transient--prefix scope) "Upstream")))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod transient-infix-set ((obj magit--git-branch:upstream) refname)
 | 
			
		||||
  (magit-set-upstream-branch (oref transient--prefix scope) refname)
 | 
			
		||||
  (oset obj value
 | 
			
		||||
        (let ((branch (oref transient--prefix scope)))
 | 
			
		||||
          (when-let ((r (magit-get "branch" branch "remote"))
 | 
			
		||||
                     (m (magit-get "branch" branch "merge")))
 | 
			
		||||
            (list r m))))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod transient-format ((obj magit--git-branch:upstream))
 | 
			
		||||
  (let ((branch (oref transient--prefix scope)))
 | 
			
		||||
    (format-spec
 | 
			
		||||
     (oref obj format)
 | 
			
		||||
     `((?k . ,(transient-format-key obj))
 | 
			
		||||
       (?r . ,(format "branch.%s.remote" branch))
 | 
			
		||||
       (?m . ,(format "branch.%s.merge" branch))
 | 
			
		||||
       (?R . ,(transient-format-value obj #'car))
 | 
			
		||||
       (?M . ,(transient-format-value obj #'cadr))))))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod transient-format-value ((obj magit--git-branch:upstream) key)
 | 
			
		||||
  (if-let ((value (funcall key (oref obj value))))
 | 
			
		||||
      (propertize value 'face 'transient-argument)
 | 
			
		||||
    (propertize "unset" 'face 'transient-inactive-argument)))
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-branch.<branch>.rebase ()
 | 
			
		||||
  :class 'magit--git-variable:choices
 | 
			
		||||
  :scope 'magit--read-branch-scope
 | 
			
		||||
  :variable "branch.%s.rebase"
 | 
			
		||||
  :fallback "pull.rebase"
 | 
			
		||||
  :choices '("true" "false")
 | 
			
		||||
  :default "false")
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-branch.<branch>.pushRemote ()
 | 
			
		||||
  :class 'magit--git-variable:choices
 | 
			
		||||
  :scope 'magit--read-branch-scope
 | 
			
		||||
  :variable "branch.%s.pushRemote"
 | 
			
		||||
  :fallback "remote.pushDefault"
 | 
			
		||||
  :choices 'magit-list-remotes)
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-pull.rebase ()
 | 
			
		||||
  :class 'magit--git-variable:choices
 | 
			
		||||
  :variable "pull.rebase"
 | 
			
		||||
  :choices '("true" "false")
 | 
			
		||||
  :default "false")
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-remote.pushDefault ()
 | 
			
		||||
  :class 'magit--git-variable:choices
 | 
			
		||||
  :variable "remote.pushDefault"
 | 
			
		||||
  :choices 'magit-list-remotes)
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-branch.autoSetupMerge ()
 | 
			
		||||
  :class 'magit--git-variable:choices
 | 
			
		||||
  :variable "branch.autoSetupMerge"
 | 
			
		||||
  :choices '("always" "true" "false")
 | 
			
		||||
  :default "true")
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-branch.autoSetupRebase ()
 | 
			
		||||
  :class 'magit--git-variable:choices
 | 
			
		||||
  :variable "branch.autoSetupRebase"
 | 
			
		||||
  :choices '("always" "local" "remote" "never")
 | 
			
		||||
  :default "never")
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-branch)
 | 
			
		||||
;;; magit-branch.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,286 +0,0 @@
 | 
			
		||||
;;; magit-clone.el --- clone a repository  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements clone commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-clone-set-remote-head nil
 | 
			
		||||
  "Whether cloning creates the symbolic-ref `<remote>/HEAD'."
 | 
			
		||||
  :package-version '(magit . "2.4.2")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-clone-set-remote.pushDefault 'ask
 | 
			
		||||
  "Whether to set the value of `remote.pushDefault' after cloning.
 | 
			
		||||
 | 
			
		||||
If t, then set without asking.  If nil, then don't set.  If
 | 
			
		||||
`ask', then ask."
 | 
			
		||||
  :package-version '(magit . "2.4.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(choice (const :tag "set" t)
 | 
			
		||||
                 (const :tag "ask" ask)
 | 
			
		||||
                 (const :tag "don't set" nil)))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-clone-default-directory nil
 | 
			
		||||
  "Default directory to use when `magit-clone' reads destination.
 | 
			
		||||
If nil (the default), then use the value of `default-directory'.
 | 
			
		||||
If a directory, then use that.  If a function, then call that
 | 
			
		||||
with the remote url as only argument and use the returned value."
 | 
			
		||||
  :package-version '(magit . "2.90.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(choice (const     :tag "value of default-directory")
 | 
			
		||||
                 (directory :tag "constant directory")
 | 
			
		||||
                 (function  :tag "function's value")))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-clone-always-transient nil
 | 
			
		||||
  "Whether `magit-clone' always acts as a transient prefix command.
 | 
			
		||||
If nil, then a prefix argument has to be used to show the transient
 | 
			
		||||
popup instead of invoking the default suffix `magit-clone-regular'
 | 
			
		||||
directly."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-clone-name-alist
 | 
			
		||||
  '(("\\`\\(?:github:\\|gh:\\)?\\([^:]+\\)\\'" "github.com" "github.user")
 | 
			
		||||
    ("\\`\\(?:gitlab:\\|gl:\\)\\([^:]+\\)\\'"  "gitlab.com" "gitlab.user"))
 | 
			
		||||
  "Alist mapping repository names to repository urls.
 | 
			
		||||
 | 
			
		||||
Each element has the form (REGEXP HOSTNAME USER).  When the user
 | 
			
		||||
enters a name when a cloning command asks for a name or url, then
 | 
			
		||||
that is looked up in this list.  The first element whose REGEXP
 | 
			
		||||
matches is used.
 | 
			
		||||
 | 
			
		||||
The format specified by option `magit-clone-url-format' is used
 | 
			
		||||
to turn the name into an url, using HOSTNAME and the repository
 | 
			
		||||
name.  If the provided name contains a slash, then that is used.
 | 
			
		||||
Otherwise if the name omits the owner of the repository, then the
 | 
			
		||||
default user specified in the matched entry is used.
 | 
			
		||||
 | 
			
		||||
If USER contains a dot, then it is treated as a Git variable and
 | 
			
		||||
the value of that is used as the username.  Otherwise it is used
 | 
			
		||||
as the username itself."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(repeat (list regexp
 | 
			
		||||
                       (string :tag "hostname")
 | 
			
		||||
                       (string :tag "user name or git variable"))))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-clone-url-format "git@%h:%n.git"
 | 
			
		||||
  "Format used when turning repository names into urls.
 | 
			
		||||
%h is the hostname and %n is the repository name, including
 | 
			
		||||
the name of the owner.  Also see `magit-clone-name-alist'."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'regexp)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-clone "magit-clone" nil t)
 | 
			
		||||
(transient-define-prefix magit-clone (&optional transient)
 | 
			
		||||
  "Clone a repository."
 | 
			
		||||
  :man-page "git-clone"
 | 
			
		||||
  ["Fetch arguments"
 | 
			
		||||
   ("-B" "Clone a single branch"  "--single-branch")
 | 
			
		||||
   ("-n" "Do not clone tags"      "--no-tags")
 | 
			
		||||
   ("-S" "Clones submodules"      "--recurse-submodules" :level 6)
 | 
			
		||||
   ("-l" "Do not optimize"        "--no-local" :level 7)]
 | 
			
		||||
  ["Setup arguments"
 | 
			
		||||
   ("-o" "Set name of remote"     ("-o" "--origin="))
 | 
			
		||||
   ("-b" "Set HEAD branch"        ("-b" "--branch="))
 | 
			
		||||
   ("-g" "Separate git directory" "--separate-git-dir="
 | 
			
		||||
    transient-read-directory :level 7)
 | 
			
		||||
   ("-t" "Use template directory" "--template="
 | 
			
		||||
    transient-read-existing-directory :level 6)]
 | 
			
		||||
  ["Local sharing arguments"
 | 
			
		||||
   ("-s" "Share objects"          ("-s" "--shared" :level 7))
 | 
			
		||||
   ("-h" "Do not use hardlinks"   "--no-hardlinks")]
 | 
			
		||||
  ["Clone"
 | 
			
		||||
   ("C" "regular"            magit-clone-regular)
 | 
			
		||||
   ("s" "shallow"            magit-clone-shallow)
 | 
			
		||||
   ("d" "shallow since date" magit-clone-shallow-since :level 7)
 | 
			
		||||
   ("e" "shallow excluding"  magit-clone-shallow-exclude :level 7)
 | 
			
		||||
   ("b" "bare"               magit-clone-bare)
 | 
			
		||||
   ("m" "mirror"             magit-clone-mirror)]
 | 
			
		||||
  (interactive (list (or magit-clone-always-transient current-prefix-arg)))
 | 
			
		||||
  (if transient
 | 
			
		||||
      (transient-setup #'magit-clone)
 | 
			
		||||
    (call-interactively #'magit-clone-regular)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clone-regular (repository directory args)
 | 
			
		||||
  "Create a clone of REPOSITORY in DIRECTORY.
 | 
			
		||||
Then show the status buffer for the new repository."
 | 
			
		||||
  (interactive (magit-clone-read-args))
 | 
			
		||||
  (magit-clone-internal repository directory args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clone-shallow (repository directory args depth)
 | 
			
		||||
  "Create a shallow clone of REPOSITORY in DIRECTORY.
 | 
			
		||||
Then show the status buffer for the new repository.
 | 
			
		||||
With a prefix argument read the DEPTH of the clone;
 | 
			
		||||
otherwise use 1."
 | 
			
		||||
  (interactive (append (magit-clone-read-args)
 | 
			
		||||
                       (list (if current-prefix-arg
 | 
			
		||||
                                 (read-number "Depth: " 1)
 | 
			
		||||
                               1))))
 | 
			
		||||
  (magit-clone-internal repository directory
 | 
			
		||||
                        (cons (format "--depth=%s" depth) args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clone-shallow-since (repository directory args date)
 | 
			
		||||
  "Create a shallow clone of REPOSITORY in DIRECTORY.
 | 
			
		||||
Then show the status buffer for the new repository.
 | 
			
		||||
Exclude commits before DATE, which is read from the
 | 
			
		||||
user."
 | 
			
		||||
  (interactive (append (magit-clone-read-args)
 | 
			
		||||
                       (list (transient-read-date "Exclude commits before: "
 | 
			
		||||
                                                  nil nil))))
 | 
			
		||||
  (magit-clone-internal repository directory
 | 
			
		||||
                        (cons (format "--shallow-since=%s" date) args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clone-shallow-exclude (repository directory args exclude)
 | 
			
		||||
  "Create a shallow clone of REPOSITORY in DIRECTORY.
 | 
			
		||||
Then show the status buffer for the new repository.
 | 
			
		||||
Exclude commits reachable from EXCLUDE, which is a
 | 
			
		||||
branch or tag read from the user."
 | 
			
		||||
  (interactive (append (magit-clone-read-args)
 | 
			
		||||
                       (list (read-string "Exclude commits reachable from: "))))
 | 
			
		||||
  (magit-clone-internal repository directory
 | 
			
		||||
                        (cons (format "--shallow-exclude=%s" exclude) args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clone-bare (repository directory args)
 | 
			
		||||
  "Create a bare clone of REPOSITORY in DIRECTORY.
 | 
			
		||||
Then show the status buffer for the new repository."
 | 
			
		||||
  (interactive (magit-clone-read-args))
 | 
			
		||||
  (magit-clone-internal repository directory (cons "--bare" args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clone-mirror (repository directory args)
 | 
			
		||||
  "Create a mirror of REPOSITORY in DIRECTORY.
 | 
			
		||||
Then show the status buffer for the new repository."
 | 
			
		||||
  (interactive (magit-clone-read-args))
 | 
			
		||||
  (magit-clone-internal repository directory (cons "--mirror" args)))
 | 
			
		||||
 | 
			
		||||
(defun magit-clone-internal (repository directory args)
 | 
			
		||||
  (let* ((checkout (not (memq (car args) '("--bare" "--mirror"))))
 | 
			
		||||
         (set-push-default
 | 
			
		||||
          (and checkout
 | 
			
		||||
               (or (eq  magit-clone-set-remote.pushDefault t)
 | 
			
		||||
                   (and magit-clone-set-remote.pushDefault
 | 
			
		||||
                        (y-or-n-p "Set `remote.pushDefault' to \"origin\"? "))))))
 | 
			
		||||
    (run-hooks 'magit-credential-hook)
 | 
			
		||||
    (setq directory (file-name-as-directory (expand-file-name directory)))
 | 
			
		||||
    (when (file-exists-p directory)
 | 
			
		||||
      (if (file-directory-p directory)
 | 
			
		||||
          (when (> (length (directory-files directory)) 2)
 | 
			
		||||
            (let ((name (magit-clone--url-to-name repository)))
 | 
			
		||||
              (unless (and name
 | 
			
		||||
                           (setq directory (file-name-as-directory
 | 
			
		||||
                                            (expand-file-name name directory)))
 | 
			
		||||
                           (not (file-exists-p directory)))
 | 
			
		||||
                (user-error "%s already exits"))))
 | 
			
		||||
        (user-error "%s already exists and is not a directory")))
 | 
			
		||||
    (magit-run-git-async "clone" args "--" repository
 | 
			
		||||
                         (magit-convert-filename-for-git directory))
 | 
			
		||||
    ;; Don't refresh the buffer we're calling from.
 | 
			
		||||
    (process-put magit-this-process 'inhibit-refresh t)
 | 
			
		||||
    (set-process-sentinel
 | 
			
		||||
     magit-this-process
 | 
			
		||||
     (lambda (process event)
 | 
			
		||||
       (when (memq (process-status process) '(exit signal))
 | 
			
		||||
         (let ((magit-process-raise-error t))
 | 
			
		||||
           (magit-process-sentinel process event)))
 | 
			
		||||
       (when (and (eq (process-status process) 'exit)
 | 
			
		||||
                  (= (process-exit-status process) 0))
 | 
			
		||||
         (when checkout
 | 
			
		||||
           (let ((default-directory directory))
 | 
			
		||||
             (when set-push-default
 | 
			
		||||
               (setf (magit-get "remote.pushDefault") "origin"))
 | 
			
		||||
             (unless magit-clone-set-remote-head
 | 
			
		||||
               (magit-remote-unset-head "origin"))))
 | 
			
		||||
         (with-current-buffer (process-get process 'command-buf)
 | 
			
		||||
           (magit-status-setup-buffer directory)))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-clone-read-args ()
 | 
			
		||||
  (let ((repo (magit-clone-read-repository)))
 | 
			
		||||
    (list repo
 | 
			
		||||
          (read-directory-name
 | 
			
		||||
           "Clone to: "
 | 
			
		||||
           (if (functionp magit-clone-default-directory)
 | 
			
		||||
               (funcall magit-clone-default-directory repo)
 | 
			
		||||
             magit-clone-default-directory)
 | 
			
		||||
           nil nil
 | 
			
		||||
           (magit-clone--url-to-name repo))
 | 
			
		||||
          (transient-args 'magit-clone))))
 | 
			
		||||
 | 
			
		||||
(defun magit-clone-read-repository ()
 | 
			
		||||
  (magit-read-char-case "Clone from " nil
 | 
			
		||||
    (?u "[u]rl or name"
 | 
			
		||||
        (let ((str (magit-read-string-ns "Clone from url or name")))
 | 
			
		||||
          (if (string-match-p "\\(://\\|@\\)" str)
 | 
			
		||||
              str
 | 
			
		||||
            (magit-clone--name-to-url str))))
 | 
			
		||||
    (?p "[p]ath"
 | 
			
		||||
        (read-directory-name "Clone repository: "))
 | 
			
		||||
    (?l "or [l]ocal url"
 | 
			
		||||
        (concat "file://" (read-directory-name "Clone repository: file://")))))
 | 
			
		||||
 | 
			
		||||
(defun magit-clone--url-to-name (url)
 | 
			
		||||
  (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" url)
 | 
			
		||||
       (match-string 1 url)))
 | 
			
		||||
 | 
			
		||||
(defun magit-clone--name-to-url (name)
 | 
			
		||||
  (or (-some
 | 
			
		||||
       (pcase-lambda (`(,re ,host ,user))
 | 
			
		||||
         (and (string-match re name)
 | 
			
		||||
              (let ((repo (match-string 1 name)))
 | 
			
		||||
                (magit-clone--format-url host user repo))))
 | 
			
		||||
       magit-clone-name-alist)
 | 
			
		||||
      (user-error "Not an url and no matching entry in `%s'"
 | 
			
		||||
                  'magit-clone-name-alist)))
 | 
			
		||||
 | 
			
		||||
(defun magit-clone--format-url (host user repo)
 | 
			
		||||
  (format-spec
 | 
			
		||||
   magit-clone-url-format
 | 
			
		||||
   `((?h . ,host)
 | 
			
		||||
     (?n . ,(if (string-match-p "/" repo)
 | 
			
		||||
                repo
 | 
			
		||||
              (if (string-match-p "\\." user)
 | 
			
		||||
                  (if-let ((user (magit-get user)))
 | 
			
		||||
                      (concat user "/" repo)
 | 
			
		||||
                    (user-error "Set %S or specify owner explicitly" user))
 | 
			
		||||
                (concat user "/" repo)))))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-clone)
 | 
			
		||||
;;; magit-clone.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,612 +0,0 @@
 | 
			
		||||
;;; magit-commit.el --- create Git commits  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements commands for creating Git commits.  These
 | 
			
		||||
;; commands just initiate the commit, support for writing the commit
 | 
			
		||||
;; messages is implemented in `git-commit.el'.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
(require 'magit-sequence)
 | 
			
		||||
 | 
			
		||||
(eval-when-compile (require 'epa)) ; for `epa-protocol'
 | 
			
		||||
(eval-when-compile (require 'epg))
 | 
			
		||||
(eval-when-compile (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-commit-ask-to-stage 'verbose
 | 
			
		||||
  "Whether to ask to stage all unstaged changes when committing and nothing is staged."
 | 
			
		||||
  :package-version '(magit . "2.3.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(choice (const :tag "Ask" t)
 | 
			
		||||
                 (const :tag "Ask showing diff" verbose)
 | 
			
		||||
                 (const :tag "Stage without confirmation" stage)
 | 
			
		||||
                 (const :tag "Don't ask" nil)))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-commit-show-diff t
 | 
			
		||||
  "Whether the relevant diff is automatically shown when committing."
 | 
			
		||||
  :package-version '(magit . "2.3.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-commit-extend-override-date t
 | 
			
		||||
  "Whether using `magit-commit-extend' changes the committer date."
 | 
			
		||||
  :package-version '(magit . "2.3.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-commit-reword-override-date t
 | 
			
		||||
  "Whether using `magit-commit-reword' changes the committer date."
 | 
			
		||||
  :package-version '(magit . "2.3.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-commit-squash-confirm t
 | 
			
		||||
  "Whether the commit targeted by squash and fixup has to be confirmed.
 | 
			
		||||
When non-nil then the commit at point (if any) is used as default
 | 
			
		||||
choice, otherwise it has to be confirmed.  This option only
 | 
			
		||||
affects `magit-commit-squash' and `magit-commit-fixup'.  The
 | 
			
		||||
\"instant\" variants always require confirmation because making
 | 
			
		||||
an error while using those is harder to recover from."
 | 
			
		||||
  :package-version '(magit . "2.1.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-post-commit-hook nil
 | 
			
		||||
  "Hook run after creating a commit without the user editing a message.
 | 
			
		||||
 | 
			
		||||
This hook is run by `magit-refresh' if `this-command' is a member
 | 
			
		||||
of `magit-post-stage-hook-commands'.  This only includes commands
 | 
			
		||||
named `magit-commit-*' that do *not* require that the user edits
 | 
			
		||||
the commit message in a buffer and then finishes by pressing
 | 
			
		||||
\\<with-editor-mode-map>\\[with-editor-finish].
 | 
			
		||||
 | 
			
		||||
Also see `git-commit-post-finish-hook'."
 | 
			
		||||
  :package-version '(magit . "2.90.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'hook)
 | 
			
		||||
 | 
			
		||||
(defvar magit-post-commit-hook-commands
 | 
			
		||||
  '(magit-commit-extend
 | 
			
		||||
    magit-commit-fixup
 | 
			
		||||
    magit-commit-augment
 | 
			
		||||
    magit-commit-instant-fixup
 | 
			
		||||
    magit-commit-instant-squash))
 | 
			
		||||
 | 
			
		||||
;;; Popup
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-commit "magit-commit" nil t)
 | 
			
		||||
(transient-define-prefix magit-commit ()
 | 
			
		||||
  "Create a new commit or replace an existing commit."
 | 
			
		||||
  :info-manual "(magit)Initiating a Commit"
 | 
			
		||||
  :man-page "git-commit"
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   ("-a" "Stage all modified and deleted files"   ("-a" "--all"))
 | 
			
		||||
   ("-e" "Allow empty commit"                     "--allow-empty")
 | 
			
		||||
   ("-v" "Show diff of changes to be committed"   ("-v" "--verbose"))
 | 
			
		||||
   ("-n" "Disable hooks"                          ("-n" "--no-verify"))
 | 
			
		||||
   ("-R" "Claim authorship and reset author date" "--reset-author")
 | 
			
		||||
   (magit:--author :description "Override the author")
 | 
			
		||||
   (7 "-D" "Override the author date" "--date=" transient-read-date)
 | 
			
		||||
   ("-s" "Add Signed-off-by line"                 ("-s" "--signoff"))
 | 
			
		||||
   (5 magit:--gpg-sign)
 | 
			
		||||
   (magit-commit:--reuse-message)]
 | 
			
		||||
  [["Create"
 | 
			
		||||
    ("c" "Commit"         magit-commit-create)]
 | 
			
		||||
   ["Edit HEAD"
 | 
			
		||||
    ("e" "Extend"         magit-commit-extend)
 | 
			
		||||
    ("w" "Reword"         magit-commit-reword)
 | 
			
		||||
    ("a" "Amend"          magit-commit-amend)
 | 
			
		||||
    (6 "n" "Reshelve"     magit-commit-reshelve)]
 | 
			
		||||
   ["Edit"
 | 
			
		||||
    ("f" "Fixup"          magit-commit-fixup)
 | 
			
		||||
    ("s" "Squash"         magit-commit-squash)
 | 
			
		||||
    ("A" "Augment"        magit-commit-augment)
 | 
			
		||||
    (6 "x" "Absorb changes" magit-commit-autofixup)]
 | 
			
		||||
   [""
 | 
			
		||||
    ("F" "Instant fixup"  magit-commit-instant-fixup)
 | 
			
		||||
    ("S" "Instant squash" magit-commit-instant-squash)]]
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if-let ((buffer (magit-commit-message-buffer)))
 | 
			
		||||
      (switch-to-buffer buffer)
 | 
			
		||||
    (transient-setup 'magit-commit)))
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-arguments nil
 | 
			
		||||
  (transient-args 'magit-commit))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit:--gpg-sign ()
 | 
			
		||||
  :description "Sign using gpg"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :shortarg "-S"
 | 
			
		||||
  :argument "--gpg-sign="
 | 
			
		||||
  :allow-empty t
 | 
			
		||||
  :reader 'magit-read-gpg-secret-key)
 | 
			
		||||
 | 
			
		||||
(defvar magit-gpg-secret-key-hist nil)
 | 
			
		||||
 | 
			
		||||
(defun magit-read-gpg-secret-key (prompt &optional initial-input history)
 | 
			
		||||
  (require 'epa)
 | 
			
		||||
  (let* ((keys (mapcar
 | 
			
		||||
                (lambda (obj)
 | 
			
		||||
                  (let ((key (epg-sub-key-id (car (epg-key-sub-key-list obj))))
 | 
			
		||||
                        (author
 | 
			
		||||
                         (when-let ((id-obj (car (epg-key-user-id-list obj))))
 | 
			
		||||
                           (let ((id-str (epg-user-id-string id-obj)))
 | 
			
		||||
                             (if (stringp id-str)
 | 
			
		||||
                                 id-str
 | 
			
		||||
                               (epg-decode-dn id-obj))))))
 | 
			
		||||
                    (propertize key 'display (concat key " " author))))
 | 
			
		||||
                (epg-list-keys (epg-make-context epa-protocol) nil t)))
 | 
			
		||||
         (choice (completing-read prompt keys nil nil nil
 | 
			
		||||
                                  history nil initial-input)))
 | 
			
		||||
    (set-text-properties 0 (length choice) nil choice)
 | 
			
		||||
    choice))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-commit:--reuse-message ()
 | 
			
		||||
  :description "Reuse commit message"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :shortarg "-C"
 | 
			
		||||
  :argument "--reuse-message="
 | 
			
		||||
  :reader 'magit-read-reuse-message
 | 
			
		||||
  :history-key 'magit-revision-history)
 | 
			
		||||
 | 
			
		||||
(defun magit-read-reuse-message (prompt &optional default history)
 | 
			
		||||
  (magit-completing-read prompt (magit-list-refnames)
 | 
			
		||||
                         nil nil nil history
 | 
			
		||||
                         (or default
 | 
			
		||||
                             (and (magit-rev-verify "ORIG_HEAD")
 | 
			
		||||
                                  "ORIG_HEAD"))))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-create (&optional args)
 | 
			
		||||
  "Create a new commit on `HEAD'.
 | 
			
		||||
With a prefix argument, amend to the commit at `HEAD' instead.
 | 
			
		||||
\n(git commit [--amend] ARGS)"
 | 
			
		||||
  (interactive (if current-prefix-arg
 | 
			
		||||
                   (list (cons "--amend" (magit-commit-arguments)))
 | 
			
		||||
                 (list (magit-commit-arguments))))
 | 
			
		||||
  (when (member "--all" args)
 | 
			
		||||
    (setq this-command 'magit-commit-all))
 | 
			
		||||
  (when (setq args (magit-commit-assert args))
 | 
			
		||||
    (let ((default-directory (magit-toplevel)))
 | 
			
		||||
      (magit-run-git-with-editor "commit" args))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-amend (&optional args)
 | 
			
		||||
  "Amend the last commit.
 | 
			
		||||
\n(git commit --amend ARGS)"
 | 
			
		||||
  (interactive (list (magit-commit-arguments)))
 | 
			
		||||
  (magit-commit-amend-assert)
 | 
			
		||||
  (magit-run-git-with-editor "commit" "--amend" args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-extend (&optional args override-date)
 | 
			
		||||
  "Amend the last commit, without editing the message.
 | 
			
		||||
 | 
			
		||||
With a prefix argument keep the committer date, otherwise change
 | 
			
		||||
it.  The option `magit-commit-extend-override-date' can be used
 | 
			
		||||
to inverse the meaning of the prefix argument.  \n(git commit
 | 
			
		||||
--amend --no-edit)"
 | 
			
		||||
  (interactive (list (magit-commit-arguments)
 | 
			
		||||
                     (if current-prefix-arg
 | 
			
		||||
                         (not magit-commit-extend-override-date)
 | 
			
		||||
                       magit-commit-extend-override-date)))
 | 
			
		||||
  (when (setq args (magit-commit-assert args (not override-date)))
 | 
			
		||||
    (magit-commit-amend-assert)
 | 
			
		||||
    (let ((process-environment process-environment))
 | 
			
		||||
      (unless override-date
 | 
			
		||||
        (push (magit-rev-format "GIT_COMMITTER_DATE=%cD") process-environment))
 | 
			
		||||
      (magit-run-git-with-editor "commit" "--amend" "--no-edit" args))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-reword (&optional args override-date)
 | 
			
		||||
  "Reword the last commit, ignoring staged changes.
 | 
			
		||||
 | 
			
		||||
With a prefix argument keep the committer date, otherwise change
 | 
			
		||||
it.  The option `magit-commit-reword-override-date' can be used
 | 
			
		||||
to inverse the meaning of the prefix argument.
 | 
			
		||||
 | 
			
		||||
Non-interactively respect the optional OVERRIDE-DATE argument
 | 
			
		||||
and ignore the option.
 | 
			
		||||
\n(git commit --amend --only)"
 | 
			
		||||
  (interactive (list (magit-commit-arguments)
 | 
			
		||||
                     (if current-prefix-arg
 | 
			
		||||
                         (not magit-commit-reword-override-date)
 | 
			
		||||
                       magit-commit-reword-override-date)))
 | 
			
		||||
  (magit-commit-amend-assert)
 | 
			
		||||
  (let ((process-environment process-environment))
 | 
			
		||||
    (unless override-date
 | 
			
		||||
      (push (magit-rev-format "GIT_COMMITTER_DATE=%cD") process-environment))
 | 
			
		||||
    (cl-pushnew "--allow-empty" args :test #'equal)
 | 
			
		||||
    (magit-run-git-with-editor "commit" "--amend" "--only" args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-fixup (&optional commit args)
 | 
			
		||||
  "Create a fixup commit.
 | 
			
		||||
 | 
			
		||||
With a prefix argument the target COMMIT has to be confirmed.
 | 
			
		||||
Otherwise the commit at point may be used without confirmation
 | 
			
		||||
depending on the value of option `magit-commit-squash-confirm'."
 | 
			
		||||
  (interactive (list (magit-commit-at-point)
 | 
			
		||||
                     (magit-commit-arguments)))
 | 
			
		||||
  (magit-commit-squash-internal "--fixup" commit args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-squash (&optional commit args)
 | 
			
		||||
  "Create a squash commit, without editing the squash message.
 | 
			
		||||
 | 
			
		||||
With a prefix argument the target COMMIT has to be confirmed.
 | 
			
		||||
Otherwise the commit at point may be used without confirmation
 | 
			
		||||
depending on the value of option `magit-commit-squash-confirm'."
 | 
			
		||||
  (interactive (list (magit-commit-at-point)
 | 
			
		||||
                     (magit-commit-arguments)))
 | 
			
		||||
  (magit-commit-squash-internal "--squash" commit args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-augment (&optional commit args)
 | 
			
		||||
  "Create a squash commit, editing the squash message.
 | 
			
		||||
 | 
			
		||||
With a prefix argument the target COMMIT has to be confirmed.
 | 
			
		||||
Otherwise the commit at point may be used without confirmation
 | 
			
		||||
depending on the value of option `magit-commit-squash-confirm'."
 | 
			
		||||
  (interactive (list (magit-commit-at-point)
 | 
			
		||||
                     (magit-commit-arguments)))
 | 
			
		||||
  (magit-commit-squash-internal "--squash" commit args nil t))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-instant-fixup (&optional commit args)
 | 
			
		||||
  "Create a fixup commit targeting COMMIT and instantly rebase."
 | 
			
		||||
  (interactive (list (magit-commit-at-point)
 | 
			
		||||
                     (magit-commit-arguments)))
 | 
			
		||||
  (magit-commit-squash-internal "--fixup" commit args t))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-instant-squash (&optional commit args)
 | 
			
		||||
  "Create a squash commit targeting COMMIT and instantly rebase."
 | 
			
		||||
  (interactive (list (magit-commit-at-point)
 | 
			
		||||
                     (magit-commit-arguments)))
 | 
			
		||||
  (magit-commit-squash-internal "--squash" commit args t))
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-squash-internal
 | 
			
		||||
    (option commit &optional args rebase edit confirmed)
 | 
			
		||||
  (when-let ((args (magit-commit-assert args t)))
 | 
			
		||||
    (when commit
 | 
			
		||||
      (when (and rebase (not (magit-rev-ancestor-p commit "HEAD")))
 | 
			
		||||
        (magit-read-char-case
 | 
			
		||||
            (format "%s isn't an ancestor of HEAD.  " commit) nil
 | 
			
		||||
          (?c "[c]reate without rebasing" (setq rebase nil))
 | 
			
		||||
          (?s "[s]elect other"            (setq commit nil))
 | 
			
		||||
          (?a "[a]bort"                   (user-error "Quit")))))
 | 
			
		||||
    (when commit
 | 
			
		||||
      (setq commit (magit-rebase-interactive-assert commit t)))
 | 
			
		||||
    (if (and commit
 | 
			
		||||
             (or confirmed
 | 
			
		||||
                 (not (or rebase
 | 
			
		||||
                          current-prefix-arg
 | 
			
		||||
                          magit-commit-squash-confirm))))
 | 
			
		||||
        (let ((magit-commit-show-diff nil))
 | 
			
		||||
          (push (concat option "=" commit) args)
 | 
			
		||||
          (unless edit
 | 
			
		||||
            (push "--no-edit" args))
 | 
			
		||||
          (if rebase
 | 
			
		||||
              (magit-with-editor
 | 
			
		||||
                (magit-call-git
 | 
			
		||||
                 "commit" "--no-gpg-sign"
 | 
			
		||||
                 (-remove-first
 | 
			
		||||
                  (apply-partially #'string-match-p "\\`--gpg-sign=")
 | 
			
		||||
                  args)))
 | 
			
		||||
            (magit-run-git-with-editor "commit" args))
 | 
			
		||||
          t) ; The commit was created; used by below lambda.
 | 
			
		||||
      (magit-log-select
 | 
			
		||||
        (lambda (commit)
 | 
			
		||||
          (when (and (magit-commit-squash-internal option commit args
 | 
			
		||||
                                                   rebase edit t)
 | 
			
		||||
                     rebase)
 | 
			
		||||
            (magit-commit-amend-assert commit)
 | 
			
		||||
            (magit-rebase-interactive-1 commit
 | 
			
		||||
                (list "--autosquash" "--autostash" "--keep-empty")
 | 
			
		||||
              "" "true" nil t)))
 | 
			
		||||
        (format "Type %%p on a commit to %s into it,"
 | 
			
		||||
                (substring option 2))
 | 
			
		||||
        nil nil nil commit)
 | 
			
		||||
      (when magit-commit-show-diff
 | 
			
		||||
        (let ((magit-display-buffer-noselect t))
 | 
			
		||||
          (apply #'magit-diff-staged nil (magit-diff-arguments)))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-amend-assert (&optional commit)
 | 
			
		||||
  (--when-let (magit-list-publishing-branches commit)
 | 
			
		||||
    (let ((m1 "This commit has already been published to ")
 | 
			
		||||
          (m2 ".\nDo you really want to modify it"))
 | 
			
		||||
      (magit-confirm 'amend-published
 | 
			
		||||
        (concat m1 "%s" m2)
 | 
			
		||||
        (concat m1 "%i public branches" m2)
 | 
			
		||||
        nil it))))
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-assert (args &optional strict)
 | 
			
		||||
  (cond
 | 
			
		||||
   ((or (magit-anything-staged-p)
 | 
			
		||||
        (and (magit-anything-unstaged-p)
 | 
			
		||||
             ;; ^ Everything of nothing is still nothing.
 | 
			
		||||
             (member "--all" args))
 | 
			
		||||
        (and (not strict)
 | 
			
		||||
             ;; ^ For amend variants that don't make sense otherwise.
 | 
			
		||||
             (or (member "--amend" args)
 | 
			
		||||
                 (member "--allow-empty" args))))
 | 
			
		||||
    (or args (list "--")))
 | 
			
		||||
   ((and (magit-rebase-in-progress-p)
 | 
			
		||||
         (not (magit-anything-unstaged-p))
 | 
			
		||||
         (y-or-n-p "Nothing staged.  Continue in-progress rebase? "))
 | 
			
		||||
    (setq this-command 'magit-rebase-continue)
 | 
			
		||||
    (magit-run-git-sequencer "rebase" "--continue")
 | 
			
		||||
    nil)
 | 
			
		||||
   ((and (file-exists-p (magit-git-dir "MERGE_MSG"))
 | 
			
		||||
         (not (magit-anything-unstaged-p)))
 | 
			
		||||
    (or args (list "--")))
 | 
			
		||||
   ((not (magit-anything-unstaged-p))
 | 
			
		||||
    (user-error "Nothing staged (or unstaged)"))
 | 
			
		||||
   (magit-commit-ask-to-stage
 | 
			
		||||
    (when (eq magit-commit-ask-to-stage 'verbose)
 | 
			
		||||
      (magit-diff-unstaged))
 | 
			
		||||
    (prog1 (when (or (eq magit-commit-ask-to-stage 'stage)
 | 
			
		||||
                     (y-or-n-p "Nothing staged.  Stage and commit all unstaged changes? "))
 | 
			
		||||
             (magit-run-git "add" "-u" ".")
 | 
			
		||||
             (or args (list "--")))
 | 
			
		||||
      (when (and (eq magit-commit-ask-to-stage 'verbose)
 | 
			
		||||
                 (derived-mode-p 'magit-diff-mode))
 | 
			
		||||
        (magit-mode-bury-buffer))))
 | 
			
		||||
   (t
 | 
			
		||||
    (user-error "Nothing staged"))))
 | 
			
		||||
 | 
			
		||||
(defvar magit--reshelve-history nil)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-commit-reshelve (date)
 | 
			
		||||
  "Change the committer date and possibly the author date of `HEAD'.
 | 
			
		||||
 | 
			
		||||
If you are the author of `HEAD', then both dates are changed,
 | 
			
		||||
otherwise only the committer date.  The current time is used
 | 
			
		||||
as the initial minibuffer input and the original author (if
 | 
			
		||||
that is you) or committer date is available as the previous
 | 
			
		||||
history element."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((author-p (magit-rev-author-p "HEAD")))
 | 
			
		||||
     (push (magit-rev-format (if author-p "%ad" "%cd") "HEAD"
 | 
			
		||||
                             (concat "--date=format:%F %T %z"))
 | 
			
		||||
           magit--reshelve-history)
 | 
			
		||||
     (list (read-string (if author-p
 | 
			
		||||
                            "Change author and committer dates to: "
 | 
			
		||||
                          "Change committer date to: ")
 | 
			
		||||
                        (cons (format-time-string "%F %T %z") 17)
 | 
			
		||||
                        'magit--reshelve-history))))
 | 
			
		||||
  (let ((process-environment process-environment))
 | 
			
		||||
    (push (concat "GIT_COMMITTER_DATE=" date) process-environment)
 | 
			
		||||
    (magit-run-git "commit" "--amend" "--no-edit"
 | 
			
		||||
                   (and (magit-rev-author-p "HEAD")
 | 
			
		||||
                        (concat "--date=" date)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-commit-absorb "magit-commit" nil t)
 | 
			
		||||
(transient-define-prefix magit-commit-absorb (phase commit args)
 | 
			
		||||
  "Spread staged changes across recent commits.
 | 
			
		||||
With a prefix argument use a transient command to select infix
 | 
			
		||||
arguments.  This command requires git-absorb executable, which
 | 
			
		||||
is available from https://github.com/tummychow/git-absorb.
 | 
			
		||||
See `magit-commit-autofixup' for an alternative implementation."
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   ("-f" "Skip safety checks"       ("-f" "--force"))
 | 
			
		||||
   ("-v" "Display more output"      ("-v" "--verbose"))]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   ("x"  "Absorb" magit-commit-absorb)]
 | 
			
		||||
  (interactive (if current-prefix-arg
 | 
			
		||||
                   (list 'transient nil nil)
 | 
			
		||||
                 (list 'select
 | 
			
		||||
                       (magit-get-upstream-branch)
 | 
			
		||||
                       (transient-args 'magit-commit-absorb))))
 | 
			
		||||
  (if (eq phase 'transient)
 | 
			
		||||
      (transient-setup 'magit-commit-absorb)
 | 
			
		||||
    (unless (executable-find "git-absorb")
 | 
			
		||||
      (user-error "This command requires the git-absorb executable, which %s"
 | 
			
		||||
                  "is available from https://github.com/tummychow/git-absorb"))
 | 
			
		||||
    (unless (magit-anything-staged-p)
 | 
			
		||||
      (if (magit-anything-unstaged-p)
 | 
			
		||||
          (if (y-or-n-p "Nothing staged.  Absorb all unstaged changes? ")
 | 
			
		||||
              (magit-with-toplevel
 | 
			
		||||
                (magit-run-git "add" "-u" "."))
 | 
			
		||||
            (user-error "Abort"))
 | 
			
		||||
        (user-error "There are no changes that could be absorbed")))
 | 
			
		||||
    (when commit
 | 
			
		||||
      (setq commit (magit-rebase-interactive-assert commit t)))
 | 
			
		||||
    (if (and commit (eq phase 'run))
 | 
			
		||||
        (progn (magit-run-git-async "absorb" "-v" args "-b" commit) t)
 | 
			
		||||
      (magit-log-select
 | 
			
		||||
        (lambda (commit)
 | 
			
		||||
          (with-no-warnings ; about non-interactive use
 | 
			
		||||
            (magit-commit-absorb 'run commit args)))
 | 
			
		||||
        nil nil nil nil commit))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-commit-autofixup "magit-commit" nil t)
 | 
			
		||||
(transient-define-prefix magit-commit-autofixup (phase commit args)
 | 
			
		||||
  "Spread unstaged changes across recent commits.
 | 
			
		||||
With a prefix argument use a transient command to select infix
 | 
			
		||||
arguments.  This command requires the git-autofixup script, which
 | 
			
		||||
is available from https://github.com/torbiak/git-autofixup.
 | 
			
		||||
See `magit-commit-absorb' for an alternative implementation."
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   (magit-autofixup:--context)
 | 
			
		||||
   (magit-autofixup:--strict)]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   ("x"  "Absorb" magit-commit-autofixup)]
 | 
			
		||||
  (interactive (if current-prefix-arg
 | 
			
		||||
                   (list 'transient nil nil)
 | 
			
		||||
                 (list 'select
 | 
			
		||||
                       (magit-get-upstream-branch)
 | 
			
		||||
                       (transient-args 'magit-commit-autofixup))))
 | 
			
		||||
  (if (eq phase 'transient)
 | 
			
		||||
      (transient-setup 'magit-commit-autofixup)
 | 
			
		||||
    (unless (executable-find "git-autofixup")
 | 
			
		||||
      (user-error "This command requires the git-autofixup script, which %s"
 | 
			
		||||
                  "is available from https://github.com/torbiak/git-autofixup"))
 | 
			
		||||
    (when (magit-anything-staged-p)
 | 
			
		||||
      (user-error "Cannot absorb when there are staged changes"))
 | 
			
		||||
    (unless (magit-anything-unstaged-p)
 | 
			
		||||
      (user-error "There are no unstaged changes that could be absorbed"))
 | 
			
		||||
    (when commit
 | 
			
		||||
      (setq commit (magit-rebase-interactive-assert commit t)))
 | 
			
		||||
    (if (and commit (eq phase 'run))
 | 
			
		||||
        (progn (magit-run-git-async "autofixup" "-vv" args commit) t)
 | 
			
		||||
      (magit-log-select
 | 
			
		||||
        (lambda (commit)
 | 
			
		||||
          (with-no-warnings ; about non-interactive use
 | 
			
		||||
            (magit-commit-autofixup 'run commit args)))
 | 
			
		||||
        nil nil nil nil commit))))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-autofixup:--context ()
 | 
			
		||||
  :description "Diff context lines"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :shortarg "-c"
 | 
			
		||||
  :argument "--context="
 | 
			
		||||
  :reader 'transient-read-number-N0)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-autofixup:--strict ()
 | 
			
		||||
  :description "Strictness"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :shortarg "-s"
 | 
			
		||||
  :argument "--strict="
 | 
			
		||||
  :reader 'transient-read-number-N0)
 | 
			
		||||
 | 
			
		||||
;;; Pending Diff
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-diff ()
 | 
			
		||||
  (when (and git-commit-mode magit-commit-show-diff)
 | 
			
		||||
    (when-let ((diff-buffer (magit-get-mode-buffer 'magit-diff-mode)))
 | 
			
		||||
      ;; This window just started displaying the commit message
 | 
			
		||||
      ;; buffer.  Without this that buffer would immediately be
 | 
			
		||||
      ;; replaced with the diff buffer.  See #2632.
 | 
			
		||||
      (unrecord-window-buffer nil diff-buffer))
 | 
			
		||||
    (condition-case nil
 | 
			
		||||
        (let ((args (car (magit-diff-arguments)))
 | 
			
		||||
              (magit-inhibit-save-previous-winconf 'unset)
 | 
			
		||||
              (magit-display-buffer-noselect t)
 | 
			
		||||
              (inhibit-quit nil)
 | 
			
		||||
              (display-buffer-overriding-action '(nil (inhibit-same-window t))))
 | 
			
		||||
          (message "Diffing changes to be committed (C-g to abort diffing)")
 | 
			
		||||
          (cl-case last-command
 | 
			
		||||
            (magit-commit
 | 
			
		||||
             (magit-diff-staged nil args))
 | 
			
		||||
            (magit-commit-all
 | 
			
		||||
             (magit-diff-working-tree nil args))
 | 
			
		||||
            ((magit-commit-amend
 | 
			
		||||
              magit-commit-reword
 | 
			
		||||
              magit-rebase-reword-commit)
 | 
			
		||||
             (magit-diff-while-amending args))
 | 
			
		||||
            (t (if (magit-anything-staged-p)
 | 
			
		||||
                   (magit-diff-staged nil args)
 | 
			
		||||
                 (magit-diff-while-amending args)))))
 | 
			
		||||
      (quit))))
 | 
			
		||||
 | 
			
		||||
;; Mention `magit-diff-while-committing' because that's
 | 
			
		||||
;; always what I search for when I try to find this line.
 | 
			
		||||
(add-hook 'server-switch-hook 'magit-commit-diff)
 | 
			
		||||
(add-hook 'with-editor-filter-visit-hook 'magit-commit-diff)
 | 
			
		||||
 | 
			
		||||
(add-to-list 'with-editor-server-window-alist
 | 
			
		||||
             (cons git-commit-filename-regexp 'switch-to-buffer))
 | 
			
		||||
 | 
			
		||||
;;; Message Utilities
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-message-buffer ()
 | 
			
		||||
  (let* ((find-file-visit-truename t) ; git uses truename of COMMIT_EDITMSG
 | 
			
		||||
         (topdir (magit-toplevel)))
 | 
			
		||||
    (--first (equal topdir (with-current-buffer it
 | 
			
		||||
                             (and git-commit-mode (magit-toplevel))))
 | 
			
		||||
             (append (buffer-list (selected-frame))
 | 
			
		||||
                     (buffer-list)))))
 | 
			
		||||
 | 
			
		||||
(defvar magit-commit-add-log-insert-function 'magit-commit-add-log-insert
 | 
			
		||||
  "Used by `magit-commit-add-log' to insert a single entry.")
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-add-log ()
 | 
			
		||||
  "Add a stub for the current change into the commit message buffer.
 | 
			
		||||
If no commit is in progress, then initiate it.  Use the function
 | 
			
		||||
specified by variable `magit-commit-add-log-insert-function' to
 | 
			
		||||
actually insert the entry."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (pcase-let* ((hunk (and (magit-section-match 'hunk)
 | 
			
		||||
                          (magit-current-section)))
 | 
			
		||||
               (log  (magit-commit-message-buffer))
 | 
			
		||||
               (`(,buf ,pos) (magit-diff-visit-file--noselect)))
 | 
			
		||||
    (unless log
 | 
			
		||||
      (unless (magit-commit-assert nil)
 | 
			
		||||
        (user-error "Abort"))
 | 
			
		||||
      (magit-commit-create)
 | 
			
		||||
      (while (not (setq log (magit-commit-message-buffer)))
 | 
			
		||||
        (sit-for 0.01)))
 | 
			
		||||
    (magit--with-temp-position buf pos
 | 
			
		||||
      (funcall magit-commit-add-log-insert-function log
 | 
			
		||||
               (magit-file-relative-name)
 | 
			
		||||
               (and hunk (add-log-current-defun))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-commit-add-log-insert (buffer file defun)
 | 
			
		||||
  (with-current-buffer buffer
 | 
			
		||||
    (undo-boundary)
 | 
			
		||||
    (goto-char (point-max))
 | 
			
		||||
    (while (re-search-backward (concat "^" comment-start) nil t))
 | 
			
		||||
    (save-restriction
 | 
			
		||||
      (narrow-to-region (point-min) (point))
 | 
			
		||||
      (cond ((re-search-backward (format "* %s\\(?: (\\([^)]+\\))\\)?: " file)
 | 
			
		||||
                                 nil t)
 | 
			
		||||
             (when (equal (match-string 1) defun)
 | 
			
		||||
               (setq defun nil))
 | 
			
		||||
             (re-search-forward ": "))
 | 
			
		||||
            (t
 | 
			
		||||
             (when (re-search-backward "^[\\*(].+\n" nil t)
 | 
			
		||||
               (goto-char (match-end 0)))
 | 
			
		||||
             (while (re-search-forward "^[^\\*\n].*\n" nil t))
 | 
			
		||||
             (if defun
 | 
			
		||||
                 (progn (insert (format "* %s (%s): \n" file defun))
 | 
			
		||||
                        (setq defun nil))
 | 
			
		||||
               (insert (format "* %s: \n" file)))
 | 
			
		||||
             (backward-char)
 | 
			
		||||
             (unless (looking-at "\n[\n\\']")
 | 
			
		||||
               (insert ?\n)
 | 
			
		||||
               (backward-char))))
 | 
			
		||||
      (when defun
 | 
			
		||||
        (forward-line)
 | 
			
		||||
        (let ((limit (save-excursion
 | 
			
		||||
                       (and (re-search-forward "^\\*" nil t)
 | 
			
		||||
                            (point)))))
 | 
			
		||||
          (unless (or (looking-back (format "(%s): " defun)
 | 
			
		||||
                                    (line-beginning-position))
 | 
			
		||||
                      (re-search-forward (format "^(%s): " defun) limit t))
 | 
			
		||||
            (while (re-search-forward "^[^\\*\n].*\n" limit t))
 | 
			
		||||
            (insert (format "(%s): \n" defun))
 | 
			
		||||
            (backward-char)))))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-commit)
 | 
			
		||||
;;; magit-commit.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,128 +0,0 @@
 | 
			
		||||
;;; magit-core.el --- core functionality  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library requires several other libraries, so that yet other
 | 
			
		||||
;; libraries can just require this one, instead of having to require
 | 
			
		||||
;; all the other ones.  In other words this separates the low-level
 | 
			
		||||
;; stuff from the rest.  It also defines some Custom groups.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit-utils)
 | 
			
		||||
(require 'magit-section)
 | 
			
		||||
(require 'magit-git)
 | 
			
		||||
(require 'magit-mode)
 | 
			
		||||
(require 'magit-margin)
 | 
			
		||||
(require 'magit-process)
 | 
			
		||||
(require 'magit-transient)
 | 
			
		||||
(require 'magit-autorevert)
 | 
			
		||||
 | 
			
		||||
(when (magit--libgit-available-p)
 | 
			
		||||
  (condition-case err
 | 
			
		||||
      (require 'magit-libgit)
 | 
			
		||||
    (error
 | 
			
		||||
     (setq magit-inhibit-libgit 'error)
 | 
			
		||||
     (message "Error while loading `magit-libgit': %S" err)
 | 
			
		||||
     (message "That is not fatal.  The `libegit2' module just won't be used."))))
 | 
			
		||||
 | 
			
		||||
(defgroup magit nil
 | 
			
		||||
  "Controlling Git from Emacs."
 | 
			
		||||
  :link '(url-link "https://magit.vc")
 | 
			
		||||
  :link '(info-link "(magit)FAQ")
 | 
			
		||||
  :link '(info-link "(magit)")
 | 
			
		||||
  :group 'tools)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-essentials nil
 | 
			
		||||
  "Options that every Magit user should briefly think about.
 | 
			
		||||
 | 
			
		||||
Each of these options falls into one or more of these categories:
 | 
			
		||||
 | 
			
		||||
* Options that affect Magit's behavior in fundamental ways.
 | 
			
		||||
* Options that affect safety.
 | 
			
		||||
* Options that affect performance.
 | 
			
		||||
* Options that are of a personal nature."
 | 
			
		||||
  :link '(info-link "(magit)Essential Settings")
 | 
			
		||||
  :group 'magit)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-miscellaneous nil
 | 
			
		||||
  "Miscellaneous Magit options."
 | 
			
		||||
  :group 'magit)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-commands nil
 | 
			
		||||
  "Options controlling behavior of certain commands."
 | 
			
		||||
  :group 'magit)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-modes nil
 | 
			
		||||
  "Modes used or provided by Magit."
 | 
			
		||||
  :group 'magit)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-buffers nil
 | 
			
		||||
  "Options concerning Magit buffers."
 | 
			
		||||
  :link '(info-link "(magit)Modes and Buffers")
 | 
			
		||||
  :group 'magit)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-refresh nil
 | 
			
		||||
  "Options controlling how Magit buffers are refreshed."
 | 
			
		||||
  :link '(info-link "(magit)Automatic Refreshing of Magit Buffers")
 | 
			
		||||
  :group 'magit
 | 
			
		||||
  :group 'magit-buffers)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-faces nil
 | 
			
		||||
  "Faces used by Magit."
 | 
			
		||||
  :group 'magit
 | 
			
		||||
  :group 'faces)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-extensions nil
 | 
			
		||||
  "Extensions to Magit."
 | 
			
		||||
  :group 'magit)
 | 
			
		||||
 | 
			
		||||
(custom-add-to-group 'magit-modes   'git-commit        'custom-group)
 | 
			
		||||
(custom-add-to-group 'magit-faces   'git-commit-faces  'custom-group)
 | 
			
		||||
(custom-add-to-group 'magit-modes   'git-rebase        'custom-group)
 | 
			
		||||
(custom-add-to-group 'magit-faces   'git-rebase-faces  'custom-group)
 | 
			
		||||
(custom-add-to-group 'magit         'magit-section     'custom-group)
 | 
			
		||||
(custom-add-to-group 'magit-faces   'magit-section-faces 'custom-group)
 | 
			
		||||
(custom-add-to-group 'magit-process 'with-editor       'custom-group)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-related nil
 | 
			
		||||
  "Options that are relevant to Magit but that are defined elsewhere."
 | 
			
		||||
  :link '(custom-group-link vc)
 | 
			
		||||
  :link '(custom-group-link smerge)
 | 
			
		||||
  :link '(custom-group-link ediff)
 | 
			
		||||
  :link '(custom-group-link auto-revert)
 | 
			
		||||
  :group 'magit
 | 
			
		||||
  :group 'magit-extensions
 | 
			
		||||
  :group 'magit-essentials)
 | 
			
		||||
 | 
			
		||||
(custom-add-to-group 'magit-related     'auto-revert-check-vc-info 'custom-variable)
 | 
			
		||||
(custom-add-to-group 'magit-auto-revert 'auto-revert-check-vc-info 'custom-variable)
 | 
			
		||||
 | 
			
		||||
(custom-add-to-group 'magit-related 'ediff-window-setup-function 'custom-variable)
 | 
			
		||||
(custom-add-to-group 'magit-related 'smerge-refine-ignore-whitespace 'custom-variable)
 | 
			
		||||
(custom-add-to-group 'magit-related 'vc-follow-symlinks 'custom-variable)
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-core)
 | 
			
		||||
;;; magit-core.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,509 +0,0 @@
 | 
			
		||||
;;; magit-ediff.el --- Ediff extension for Magit  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library provides basic support for Ediff.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
(require 'ediff)
 | 
			
		||||
(require 'smerge-mode)
 | 
			
		||||
 | 
			
		||||
(defvar smerge-ediff-buf)
 | 
			
		||||
(defvar smerge-ediff-windows)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defgroup magit-ediff nil
 | 
			
		||||
  "Ediff support for Magit."
 | 
			
		||||
  :link '(info-link "(magit)Ediffing")
 | 
			
		||||
  :group 'magit-extensions)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-ediff-quit-hook
 | 
			
		||||
  '(magit-ediff-cleanup-auxiliary-buffers
 | 
			
		||||
    magit-ediff-restore-previous-winconf)
 | 
			
		||||
  "Hooks to run after finishing Ediff, when that was invoked using Magit.
 | 
			
		||||
The hooks are run in the Ediff control buffer.  This is similar
 | 
			
		||||
to `ediff-quit-hook' but takes the needs of Magit into account.
 | 
			
		||||
The `ediff-quit-hook' is ignored by Ediff sessions which were
 | 
			
		||||
invoked using Magit."
 | 
			
		||||
  :package-version '(magit . "2.2.0")
 | 
			
		||||
  :group 'magit-ediff
 | 
			
		||||
  :type 'hook
 | 
			
		||||
  :get 'magit-hook-custom-get
 | 
			
		||||
  :options '(magit-ediff-cleanup-auxiliary-buffers
 | 
			
		||||
             magit-ediff-restore-previous-winconf))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-ediff-dwim-show-on-hunks nil
 | 
			
		||||
  "Whether `magit-ediff-dwim' runs show variants on hunks.
 | 
			
		||||
If non-nil, `magit-ediff-show-staged' or
 | 
			
		||||
`magit-ediff-show-unstaged' are called based on what section the
 | 
			
		||||
hunk is in.  Otherwise, `magit-ediff-dwim' runs
 | 
			
		||||
`magit-ediff-stage' when point is on an uncommitted hunk."
 | 
			
		||||
  :package-version '(magit . "2.2.0")
 | 
			
		||||
  :group 'magit-ediff
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-ediff-show-stash-with-index t
 | 
			
		||||
  "Whether `magit-ediff-show-stash' shows the state of the index.
 | 
			
		||||
 | 
			
		||||
If non-nil, use a third Ediff buffer to distinguish which changes
 | 
			
		||||
in the stash were staged.  In cases where the stash contains no
 | 
			
		||||
staged changes, fall back to a two-buffer Ediff.
 | 
			
		||||
 | 
			
		||||
More specifically, a stash is a merge commit, stash@{N}, with
 | 
			
		||||
potentially three parents.
 | 
			
		||||
 | 
			
		||||
* stash@{N}^1 represents the `HEAD' commit at the time the stash
 | 
			
		||||
  was created.
 | 
			
		||||
 | 
			
		||||
* stash@{N}^2 records any changes that were staged when the stash
 | 
			
		||||
  was made.
 | 
			
		||||
 | 
			
		||||
* stash@{N}^3, if it exists, contains files that were untracked
 | 
			
		||||
  when stashing.
 | 
			
		||||
 | 
			
		||||
If this option is non-nil, `magit-ediff-show-stash' will run
 | 
			
		||||
Ediff on a file using three buffers: one for stash@{N}, another
 | 
			
		||||
for stash@{N}^1, and a third for stash@{N}^2.
 | 
			
		||||
 | 
			
		||||
Otherwise, Ediff uses two buffers, comparing
 | 
			
		||||
stash@{N}^1..stash@{N}.  Along with any unstaged changes, changes
 | 
			
		||||
in the index commit, stash@{N}^2, will be shown in this
 | 
			
		||||
comparison unless they conflicted with changes in the working
 | 
			
		||||
tree at the time of stashing."
 | 
			
		||||
  :package-version '(magit . "2.6.0")
 | 
			
		||||
  :group 'magit-ediff
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
(defvar magit-ediff-previous-winconf nil)
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-ediff "magit-ediff" nil)
 | 
			
		||||
(transient-define-prefix magit-ediff ()
 | 
			
		||||
  "Show differences using the Ediff package."
 | 
			
		||||
  :info-manual "(ediff)"
 | 
			
		||||
  ["Ediff"
 | 
			
		||||
   [("E" "Dwim"          magit-ediff-dwim)
 | 
			
		||||
    ("s" "Stage"         magit-ediff-stage)
 | 
			
		||||
    ("m" "Resolve"       magit-ediff-resolve)]
 | 
			
		||||
   [("u" "Show unstaged" magit-ediff-show-unstaged)
 | 
			
		||||
    ("i" "Show staged"   magit-ediff-show-staged)
 | 
			
		||||
    ("w" "Show worktree" magit-ediff-show-working-tree)]
 | 
			
		||||
   [("c" "Show commit"   magit-ediff-show-commit)
 | 
			
		||||
    ("r" "Show range"    magit-ediff-compare)
 | 
			
		||||
    ("z" "Show stash"    magit-ediff-show-stash)]])
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-resolve (file)
 | 
			
		||||
  "Resolve outstanding conflicts in FILE using Ediff.
 | 
			
		||||
FILE has to be relative to the top directory of the repository.
 | 
			
		||||
 | 
			
		||||
In the rare event that you want to manually resolve all
 | 
			
		||||
conflicts, including those already resolved by Git, use
 | 
			
		||||
`ediff-merge-revisions-with-ancestor'."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((current  (magit-current-file))
 | 
			
		||||
         (unmerged (magit-unmerged-files)))
 | 
			
		||||
     (unless unmerged
 | 
			
		||||
       (user-error "There are no unresolved conflicts"))
 | 
			
		||||
     (list (magit-completing-read "Resolve file" unmerged nil t nil nil
 | 
			
		||||
                                  (car (member current unmerged))))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (with-current-buffer (find-file-noselect file)
 | 
			
		||||
      (smerge-ediff)
 | 
			
		||||
      (setq-local
 | 
			
		||||
       ediff-quit-hook
 | 
			
		||||
       (lambda ()
 | 
			
		||||
         (let ((bufC ediff-buffer-C)
 | 
			
		||||
               (bufS smerge-ediff-buf))
 | 
			
		||||
           (with-current-buffer bufS
 | 
			
		||||
             (when (yes-or-no-p (format "Conflict resolution finished; save %s? "
 | 
			
		||||
                                        buffer-file-name))
 | 
			
		||||
               (erase-buffer)
 | 
			
		||||
               (insert-buffer-substring bufC)
 | 
			
		||||
               (save-buffer))))
 | 
			
		||||
         (when (buffer-live-p ediff-buffer-A) (kill-buffer ediff-buffer-A))
 | 
			
		||||
         (when (buffer-live-p ediff-buffer-B) (kill-buffer ediff-buffer-B))
 | 
			
		||||
         (when (buffer-live-p ediff-buffer-C) (kill-buffer ediff-buffer-C))
 | 
			
		||||
         (when (buffer-live-p ediff-ancestor-buffer)
 | 
			
		||||
           (kill-buffer ediff-ancestor-buffer))
 | 
			
		||||
         (let ((magit-ediff-previous-winconf smerge-ediff-windows))
 | 
			
		||||
           (run-hooks 'magit-ediff-quit-hook)))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-stage (file)
 | 
			
		||||
  "Stage and unstage changes to FILE using Ediff.
 | 
			
		||||
FILE has to be relative to the top directory of the repository."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((files (magit-tracked-files)))
 | 
			
		||||
     (list (magit-completing-read "Selectively stage file" files nil t nil nil
 | 
			
		||||
                                  (car (member (magit-current-file) files))))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (let* ((conf (current-window-configuration))
 | 
			
		||||
           (bufA (magit-get-revision-buffer "HEAD" file))
 | 
			
		||||
           (bufB (magit-get-revision-buffer "{index}" file))
 | 
			
		||||
           (bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only))))
 | 
			
		||||
           (bufC (get-file-buffer file))
 | 
			
		||||
           (fileBufC (or bufC (find-file-noselect file)))
 | 
			
		||||
           (coding-system-for-read
 | 
			
		||||
            (with-current-buffer fileBufC buffer-file-coding-system)))
 | 
			
		||||
      (ediff-buffers3
 | 
			
		||||
       (or bufA (magit-find-file-noselect "HEAD" file))
 | 
			
		||||
       (with-current-buffer (magit-find-file-index-noselect file t)
 | 
			
		||||
         (setq buffer-read-only nil)
 | 
			
		||||
         (current-buffer))
 | 
			
		||||
       fileBufC
 | 
			
		||||
       `((lambda ()
 | 
			
		||||
           (setq-local
 | 
			
		||||
            ediff-quit-hook
 | 
			
		||||
            (lambda ()
 | 
			
		||||
              (and (buffer-live-p ediff-buffer-B)
 | 
			
		||||
                   (buffer-modified-p ediff-buffer-B)
 | 
			
		||||
                   (with-current-buffer ediff-buffer-B
 | 
			
		||||
                     (magit-update-index)))
 | 
			
		||||
              (and (buffer-live-p ediff-buffer-C)
 | 
			
		||||
                   (buffer-modified-p ediff-buffer-C)
 | 
			
		||||
                   (with-current-buffer ediff-buffer-C
 | 
			
		||||
                     (when (y-or-n-p
 | 
			
		||||
                            (format "Save file %s? " buffer-file-name))
 | 
			
		||||
                       (save-buffer))))
 | 
			
		||||
              ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
 | 
			
		||||
              ,@(if bufB
 | 
			
		||||
                    (unless bufBrw '((with-current-buffer ediff-buffer-B
 | 
			
		||||
                                       (setq buffer-read-only t))))
 | 
			
		||||
                  '((ediff-kill-buffer-carefully ediff-buffer-B)))
 | 
			
		||||
              ,@(unless bufC '((ediff-kill-buffer-carefully ediff-buffer-C)))
 | 
			
		||||
              (let ((magit-ediff-previous-winconf ,conf))
 | 
			
		||||
                (run-hooks 'magit-ediff-quit-hook))))))
 | 
			
		||||
       'ediff-buffers3))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-compare (revA revB fileA fileB)
 | 
			
		||||
  "Compare REVA:FILEA with REVB:FILEB using Ediff.
 | 
			
		||||
 | 
			
		||||
FILEA and FILEB have to be relative to the top directory of the
 | 
			
		||||
repository.  If REVA or REVB is nil, then this stands for the
 | 
			
		||||
working tree state.
 | 
			
		||||
 | 
			
		||||
If the region is active, use the revisions on the first and last
 | 
			
		||||
line of the region.  With a prefix argument, instead of diffing
 | 
			
		||||
the revisions, choose a revision to view changes along, starting
 | 
			
		||||
at the common ancestor of both revisions (i.e., use a \"...\"
 | 
			
		||||
range)."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (pcase-let ((`(,revA ,revB) (magit-ediff-compare--read-revisions
 | 
			
		||||
                                nil current-prefix-arg)))
 | 
			
		||||
     (nconc (list revA revB)
 | 
			
		||||
            (magit-ediff-read-files revA revB))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (let ((conf (current-window-configuration))
 | 
			
		||||
          (bufA (if revA
 | 
			
		||||
                    (magit-get-revision-buffer revA fileA)
 | 
			
		||||
                  (get-file-buffer fileA)))
 | 
			
		||||
          (bufB (if revB
 | 
			
		||||
                    (magit-get-revision-buffer revB fileB)
 | 
			
		||||
                  (get-file-buffer fileB))))
 | 
			
		||||
      (ediff-buffers
 | 
			
		||||
       (or bufA (if revA
 | 
			
		||||
                    (magit-find-file-noselect revA fileA)
 | 
			
		||||
                  (find-file-noselect fileA)))
 | 
			
		||||
       (or bufB (if revB
 | 
			
		||||
                    (magit-find-file-noselect revB fileB)
 | 
			
		||||
                  (find-file-noselect fileB)))
 | 
			
		||||
       `((lambda ()
 | 
			
		||||
           (setq-local
 | 
			
		||||
            ediff-quit-hook
 | 
			
		||||
            (lambda ()
 | 
			
		||||
              ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
 | 
			
		||||
              ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
 | 
			
		||||
              (let ((magit-ediff-previous-winconf ,conf))
 | 
			
		||||
                (run-hooks 'magit-ediff-quit-hook))))))
 | 
			
		||||
       'ediff-revision))))
 | 
			
		||||
 | 
			
		||||
(defun magit-ediff-compare--read-revisions (&optional arg mbase)
 | 
			
		||||
  (let ((input (or arg (magit-diff-read-range-or-commit
 | 
			
		||||
                        "Compare range or commit"
 | 
			
		||||
                        nil mbase))))
 | 
			
		||||
    (--if-let (magit-split-range input)
 | 
			
		||||
        (-cons-to-list it)
 | 
			
		||||
      (list input nil))))
 | 
			
		||||
 | 
			
		||||
(defun magit-ediff-read-files (revA revB &optional fileB)
 | 
			
		||||
  "Read file in REVB, return it and the corresponding file in REVA.
 | 
			
		||||
When FILEB is non-nil, use this as REVB's file instead of
 | 
			
		||||
prompting for it."
 | 
			
		||||
  (unless fileB
 | 
			
		||||
    (setq fileB (magit-read-file-choice
 | 
			
		||||
                 (format "File to compare between %s and %s"
 | 
			
		||||
                         revA (or revB "the working tree"))
 | 
			
		||||
                 (magit-changed-files revA revB)
 | 
			
		||||
                 (format "No changed files between %s and %s"
 | 
			
		||||
                         revA (or revB "the working tree")))))
 | 
			
		||||
  (list (or (car (member fileB (magit-revision-files revA)))
 | 
			
		||||
            (cdr (assoc fileB (magit-renamed-files revB revA)))
 | 
			
		||||
            (magit-read-file-choice
 | 
			
		||||
             (format "File in %s to compare with %s in %s"
 | 
			
		||||
                     revA fileB (or revB "the working tree"))
 | 
			
		||||
             (magit-changed-files revB revA)
 | 
			
		||||
             (format "No files have changed between %s and %s"
 | 
			
		||||
                     revA revB)))
 | 
			
		||||
        fileB))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-dwim ()
 | 
			
		||||
  "Compare, stage, or resolve using Ediff.
 | 
			
		||||
This command tries to guess what file, and what commit or range
 | 
			
		||||
the user wants to compare, stage, or resolve using Ediff.  It
 | 
			
		||||
might only be able to guess either the file, or range or commit,
 | 
			
		||||
in which case the user is asked about the other.  It might not
 | 
			
		||||
always guess right, in which case the appropriate `magit-ediff-*'
 | 
			
		||||
command has to be used explicitly.  If it cannot read the user's
 | 
			
		||||
mind at all, then it asks the user for a command to run."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-section-case
 | 
			
		||||
    (hunk (save-excursion
 | 
			
		||||
            (goto-char (oref (oref it parent) start))
 | 
			
		||||
            (magit-ediff-dwim)))
 | 
			
		||||
    (t
 | 
			
		||||
     (let ((range (magit-diff--dwim))
 | 
			
		||||
           (file (magit-current-file))
 | 
			
		||||
           command revA revB)
 | 
			
		||||
       (pcase range
 | 
			
		||||
         ((and (guard (not magit-ediff-dwim-show-on-hunks))
 | 
			
		||||
               (or `unstaged `staged))
 | 
			
		||||
          (setq command (if (magit-anything-unmerged-p)
 | 
			
		||||
                            #'magit-ediff-resolve
 | 
			
		||||
                          #'magit-ediff-stage)))
 | 
			
		||||
         (`unstaged (setq command #'magit-ediff-show-unstaged))
 | 
			
		||||
         (`staged (setq command #'magit-ediff-show-staged))
 | 
			
		||||
         (`(commit . ,value)
 | 
			
		||||
          (setq command #'magit-ediff-show-commit)
 | 
			
		||||
          (setq revB value))
 | 
			
		||||
         (`(stash . ,value)
 | 
			
		||||
          (setq command #'magit-ediff-show-stash)
 | 
			
		||||
          (setq revB value))
 | 
			
		||||
         ((pred stringp)
 | 
			
		||||
          (pcase-let ((`(,a ,b) (magit-ediff-compare--read-revisions range)))
 | 
			
		||||
            (setq command #'magit-ediff-compare)
 | 
			
		||||
            (setq revA a)
 | 
			
		||||
            (setq revB b)))
 | 
			
		||||
         (_
 | 
			
		||||
          (when (derived-mode-p 'magit-diff-mode)
 | 
			
		||||
            (pcase (magit-diff-type)
 | 
			
		||||
              (`committed (pcase-let ((`(,a ,b)
 | 
			
		||||
                                       (magit-ediff-compare--read-revisions
 | 
			
		||||
                                        magit-buffer-range)))
 | 
			
		||||
                            (setq revA a)
 | 
			
		||||
                            (setq revB b)))
 | 
			
		||||
              ((guard (not magit-ediff-dwim-show-on-hunks))
 | 
			
		||||
               (setq command #'magit-ediff-stage))
 | 
			
		||||
              (`unstaged  (setq command #'magit-ediff-show-unstaged))
 | 
			
		||||
              (`staged    (setq command #'magit-ediff-show-staged))
 | 
			
		||||
              (`undefined (setq command nil))
 | 
			
		||||
              (_          (setq command nil))))))
 | 
			
		||||
       (cond ((not command)
 | 
			
		||||
              (call-interactively
 | 
			
		||||
               (magit-read-char-case
 | 
			
		||||
                   "Failed to read your mind; do you want to " t
 | 
			
		||||
                 (?c "[c]ommit"  'magit-ediff-show-commit)
 | 
			
		||||
                 (?r "[r]ange"   'magit-ediff-compare)
 | 
			
		||||
                 (?s "[s]tage"   'magit-ediff-stage)
 | 
			
		||||
                 (?v "resol[v]e" 'magit-ediff-resolve))))
 | 
			
		||||
             ((eq command 'magit-ediff-compare)
 | 
			
		||||
              (apply 'magit-ediff-compare revA revB
 | 
			
		||||
                     (magit-ediff-read-files revA revB file)))
 | 
			
		||||
             ((eq command 'magit-ediff-show-commit)
 | 
			
		||||
              (magit-ediff-show-commit revB))
 | 
			
		||||
             ((eq command 'magit-ediff-show-stash)
 | 
			
		||||
              (magit-ediff-show-stash revB))
 | 
			
		||||
             (file
 | 
			
		||||
              (funcall command file))
 | 
			
		||||
             (t
 | 
			
		||||
              (call-interactively command)))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-show-staged (file)
 | 
			
		||||
  "Show staged changes using Ediff.
 | 
			
		||||
 | 
			
		||||
This only allows looking at the changes; to stage, unstage,
 | 
			
		||||
and discard changes using Ediff, use `magit-ediff-stage'.
 | 
			
		||||
 | 
			
		||||
FILE must be relative to the top directory of the repository."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Show staged changes for file"
 | 
			
		||||
                                 (magit-staged-files)
 | 
			
		||||
                                 "No staged files")))
 | 
			
		||||
  (let ((conf (current-window-configuration))
 | 
			
		||||
        (bufA (magit-get-revision-buffer "HEAD" file))
 | 
			
		||||
        (bufB (get-buffer (concat file ".~{index}~"))))
 | 
			
		||||
    (ediff-buffers
 | 
			
		||||
     (or bufA (magit-find-file-noselect "HEAD" file))
 | 
			
		||||
     (or bufB (magit-find-file-index-noselect file t))
 | 
			
		||||
     `((lambda ()
 | 
			
		||||
         (setq-local
 | 
			
		||||
          ediff-quit-hook
 | 
			
		||||
          (lambda ()
 | 
			
		||||
            ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
 | 
			
		||||
            ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
 | 
			
		||||
            (let ((magit-ediff-previous-winconf ,conf))
 | 
			
		||||
              (run-hooks 'magit-ediff-quit-hook))))))
 | 
			
		||||
     'ediff-buffers)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-show-unstaged (file)
 | 
			
		||||
  "Show unstaged changes using Ediff.
 | 
			
		||||
 | 
			
		||||
This only allows looking at the changes; to stage, unstage,
 | 
			
		||||
and discard changes using Ediff, use `magit-ediff-stage'.
 | 
			
		||||
 | 
			
		||||
FILE must be relative to the top directory of the repository."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Show unstaged changes for file"
 | 
			
		||||
                                 (magit-unstaged-files)
 | 
			
		||||
                                 "No unstaged files")))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (let ((conf (current-window-configuration))
 | 
			
		||||
          (bufA (get-buffer (concat file ".~{index}~")))
 | 
			
		||||
          (bufB (get-file-buffer file)))
 | 
			
		||||
      (ediff-buffers
 | 
			
		||||
       (or bufA (magit-find-file-index-noselect file t))
 | 
			
		||||
       (or bufB (find-file-noselect file))
 | 
			
		||||
       `((lambda ()
 | 
			
		||||
           (setq-local
 | 
			
		||||
            ediff-quit-hook
 | 
			
		||||
            (lambda ()
 | 
			
		||||
              ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
 | 
			
		||||
              ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
 | 
			
		||||
              (let ((magit-ediff-previous-winconf ,conf))
 | 
			
		||||
                (run-hooks 'magit-ediff-quit-hook))))))
 | 
			
		||||
       'ediff-buffers))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-show-working-tree (file)
 | 
			
		||||
  "Show changes between `HEAD' and working tree using Ediff.
 | 
			
		||||
FILE must be relative to the top directory of the repository."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Show changes in file"
 | 
			
		||||
                                 (magit-changed-files "HEAD")
 | 
			
		||||
                                 "No changed files")))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (let ((conf (current-window-configuration))
 | 
			
		||||
          (bufA (magit-get-revision-buffer "HEAD" file))
 | 
			
		||||
          (bufB (get-file-buffer file)))
 | 
			
		||||
      (ediff-buffers
 | 
			
		||||
       (or bufA (magit-find-file-noselect "HEAD" file))
 | 
			
		||||
       (or bufB (find-file-noselect file))
 | 
			
		||||
       `((lambda ()
 | 
			
		||||
           (setq-local
 | 
			
		||||
            ediff-quit-hook
 | 
			
		||||
            (lambda ()
 | 
			
		||||
              ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A)))
 | 
			
		||||
              ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B)))
 | 
			
		||||
              (let ((magit-ediff-previous-winconf ,conf))
 | 
			
		||||
                (run-hooks 'magit-ediff-quit-hook))))))
 | 
			
		||||
       'ediff-buffers))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-show-commit (commit)
 | 
			
		||||
  "Show changes introduced by COMMIT using Ediff."
 | 
			
		||||
  (interactive (list (magit-read-branch-or-commit "Revision")))
 | 
			
		||||
  (let ((revA (concat commit "^"))
 | 
			
		||||
        (revB commit))
 | 
			
		||||
    (apply #'magit-ediff-compare
 | 
			
		||||
           revA revB
 | 
			
		||||
           (magit-ediff-read-files revA revB (magit-current-file)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-ediff-show-stash (stash)
 | 
			
		||||
  "Show changes introduced by STASH using Ediff.
 | 
			
		||||
`magit-ediff-show-stash-with-index' controls whether a
 | 
			
		||||
three-buffer Ediff is used in order to distinguish changes in the
 | 
			
		||||
stash that were staged."
 | 
			
		||||
  (interactive (list (magit-read-stash "Stash")))
 | 
			
		||||
  (pcase-let* ((revA (concat stash "^1"))
 | 
			
		||||
               (revB (concat stash "^2"))
 | 
			
		||||
               (revC stash)
 | 
			
		||||
               (`(,fileA ,fileC) (magit-ediff-read-files revA revC))
 | 
			
		||||
               (fileB fileC))
 | 
			
		||||
    (if (and magit-ediff-show-stash-with-index
 | 
			
		||||
             (member fileA (magit-changed-files revB revA)))
 | 
			
		||||
        (let ((conf (current-window-configuration))
 | 
			
		||||
              (bufA (magit-get-revision-buffer revA fileA))
 | 
			
		||||
              (bufB (magit-get-revision-buffer revB fileB))
 | 
			
		||||
              (bufC (magit-get-revision-buffer revC fileC)))
 | 
			
		||||
          (ediff-buffers3
 | 
			
		||||
           (or bufA (magit-find-file-noselect revA fileA))
 | 
			
		||||
           (or bufB (magit-find-file-noselect revB fileB))
 | 
			
		||||
           (or bufC (magit-find-file-noselect revC fileC))
 | 
			
		||||
           `((lambda ()
 | 
			
		||||
               (setq-local
 | 
			
		||||
                ediff-quit-hook
 | 
			
		||||
                (lambda ()
 | 
			
		||||
                  ,@(unless bufA
 | 
			
		||||
                      '((ediff-kill-buffer-carefully ediff-buffer-A)))
 | 
			
		||||
                  ,@(unless bufB
 | 
			
		||||
                      '((ediff-kill-buffer-carefully ediff-buffer-B)))
 | 
			
		||||
                  ,@(unless bufC
 | 
			
		||||
                      '((ediff-kill-buffer-carefully ediff-buffer-C)))
 | 
			
		||||
                  (let ((magit-ediff-previous-winconf ,conf))
 | 
			
		||||
                    (run-hooks 'magit-ediff-quit-hook))))))
 | 
			
		||||
           'ediff-buffers3))
 | 
			
		||||
      (magit-ediff-compare revA revC fileA fileC))))
 | 
			
		||||
 | 
			
		||||
(defun magit-ediff-cleanup-auxiliary-buffers ()
 | 
			
		||||
  (let* ((ctl-buf ediff-control-buffer)
 | 
			
		||||
         (ctl-win (ediff-get-visible-buffer-window ctl-buf))
 | 
			
		||||
         (ctl-frm ediff-control-frame)
 | 
			
		||||
         (main-frame (cond ((window-live-p ediff-window-A)
 | 
			
		||||
                            (window-frame ediff-window-A))
 | 
			
		||||
                           ((window-live-p ediff-window-B)
 | 
			
		||||
                            (window-frame ediff-window-B)))))
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-diff-buffer)
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-custom-diff-buffer)
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-tmp-buffer)
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-error-buffer)
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-msg-buffer)
 | 
			
		||||
    (ediff-kill-buffer-carefully ediff-debug-buffer)
 | 
			
		||||
    (when (boundp 'ediff-patch-diagnostics)
 | 
			
		||||
      (ediff-kill-buffer-carefully ediff-patch-diagnostics))
 | 
			
		||||
    (cond ((and (ediff-window-display-p)
 | 
			
		||||
                (frame-live-p ctl-frm))
 | 
			
		||||
           (delete-frame ctl-frm))
 | 
			
		||||
          ((window-live-p ctl-win)
 | 
			
		||||
           (delete-window ctl-win)))
 | 
			
		||||
    (ediff-kill-buffer-carefully ctl-buf)
 | 
			
		||||
    (when (frame-live-p main-frame)
 | 
			
		||||
      (select-frame main-frame))))
 | 
			
		||||
 | 
			
		||||
(defun magit-ediff-restore-previous-winconf ()
 | 
			
		||||
  (set-window-configuration magit-ediff-previous-winconf))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-ediff)
 | 
			
		||||
;;; magit-ediff.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,700 +0,0 @@
 | 
			
		||||
;;; magit-extras.el --- additional functionality for Magit  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Additional functionality for Magit.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
(declare-function dired-read-shell-command "dired-aux" (prompt arg files))
 | 
			
		||||
;; For `magit-project-status'.
 | 
			
		||||
(declare-function project-root "project" (project))
 | 
			
		||||
 | 
			
		||||
(defvar ido-exit)
 | 
			
		||||
(defvar ido-fallback)
 | 
			
		||||
(defvar project-prefix-map)
 | 
			
		||||
(defvar project-switch-commands)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-extras nil
 | 
			
		||||
  "Additional functionality for Magit."
 | 
			
		||||
  :group 'magit-extensions)
 | 
			
		||||
 | 
			
		||||
;;; External Tools
 | 
			
		||||
 | 
			
		||||
(defcustom magit-gitk-executable
 | 
			
		||||
  (or (and (eq system-type 'windows-nt)
 | 
			
		||||
           (let ((exe (magit-git-string
 | 
			
		||||
                       "-c" "alias.X=!x() { which \"$1\" | cygpath -mf -; }; x"
 | 
			
		||||
                       "X" "gitk.exe")))
 | 
			
		||||
             (and exe (file-executable-p exe) exe)))
 | 
			
		||||
      (executable-find "gitk") "gitk")
 | 
			
		||||
  "The Gitk executable."
 | 
			
		||||
  :group 'magit-extras
 | 
			
		||||
  :set-after '(magit-git-executable)
 | 
			
		||||
  :type 'string)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-run-git-gui ()
 | 
			
		||||
  "Run `git gui' for the current git repository."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-process-file magit-git-executable nil 0 nil "gui")))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-run-git-gui-blame (commit filename &optional linenum)
 | 
			
		||||
  "Run `git gui blame' on the given FILENAME and COMMIT.
 | 
			
		||||
Interactively run it for the current file and the `HEAD', with a
 | 
			
		||||
prefix or when the current file cannot be determined let the user
 | 
			
		||||
choose.  When the current buffer is visiting FILENAME instruct
 | 
			
		||||
blame to center around the line point is on."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let (revision filename)
 | 
			
		||||
     (when (or current-prefix-arg
 | 
			
		||||
               (not (setq revision "HEAD"
 | 
			
		||||
                          filename (magit-file-relative-name nil 'tracked))))
 | 
			
		||||
       (setq revision (magit-read-branch-or-commit "Blame from revision"))
 | 
			
		||||
       (setq filename (magit-read-file-from-rev revision "Blame file")))
 | 
			
		||||
     (list revision filename
 | 
			
		||||
           (and (equal filename
 | 
			
		||||
                       (ignore-errors
 | 
			
		||||
                         (magit-file-relative-name buffer-file-name)))
 | 
			
		||||
                (line-number-at-pos)))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (apply #'magit-process-file magit-git-executable nil 0 nil "gui" "blame"
 | 
			
		||||
           `(,@(and linenum (list (format "--line=%d" linenum)))
 | 
			
		||||
             ,commit
 | 
			
		||||
             ,filename))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-run-gitk ()
 | 
			
		||||
  "Run `gitk' in the current repository."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-process-file magit-gitk-executable nil 0))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-run-gitk-branches ()
 | 
			
		||||
  "Run `gitk --branches' in the current repository."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-process-file magit-gitk-executable nil 0 nil "--branches"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-run-gitk-all ()
 | 
			
		||||
  "Run `gitk --all' in the current repository."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-process-file magit-gitk-executable nil 0 nil "--all"))
 | 
			
		||||
 | 
			
		||||
;;; Emacs Tools
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun ido-enter-magit-status ()
 | 
			
		||||
  "Drop into `magit-status' from file switching.
 | 
			
		||||
 | 
			
		||||
This command does not work in Emacs 26.1.
 | 
			
		||||
See https://github.com/magit/magit/issues/3634
 | 
			
		||||
and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31707.
 | 
			
		||||
 | 
			
		||||
To make this command available use something like:
 | 
			
		||||
 | 
			
		||||
  (add-hook \\='ido-setup-hook
 | 
			
		||||
            (lambda ()
 | 
			
		||||
              (define-key ido-completion-map
 | 
			
		||||
                (kbd \"C-x g\") \\='ido-enter-magit-status)))
 | 
			
		||||
 | 
			
		||||
Starting with Emacs 25.1 the Ido keymaps are defined just once
 | 
			
		||||
instead of every time Ido is invoked, so now you can modify it
 | 
			
		||||
like pretty much every other keymap:
 | 
			
		||||
 | 
			
		||||
  (define-key ido-common-completion-map
 | 
			
		||||
    (kbd \"C-x g\") \\='ido-enter-magit-status)"
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (setq ido-exit 'fallback)
 | 
			
		||||
  (setq ido-fallback 'magit-status)                ; for Emacs >= 26.2
 | 
			
		||||
  (with-no-warnings (setq fallback 'magit-status)) ; for Emacs 25
 | 
			
		||||
  (exit-minibuffer))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-project-status ()
 | 
			
		||||
  "Run `magit-status' in the current project's root."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-status-setup-buffer (project-root (project-current t))))
 | 
			
		||||
 | 
			
		||||
(with-eval-after-load 'project
 | 
			
		||||
  ;; Only more recent versions of project.el have `project-prefix-map' and
 | 
			
		||||
  ;; `project-switch-commands', though project.el is available in Emacs 25.
 | 
			
		||||
  (when (boundp 'project-prefix-map)
 | 
			
		||||
    (define-key project-prefix-map "m" #'magit-project-status))
 | 
			
		||||
  (when (boundp 'project-switch-commands)
 | 
			
		||||
    (add-to-list 'project-switch-commands '(?m "Magit" magit-status))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-dired-jump (&optional other-window)
 | 
			
		||||
  "Visit file at point using Dired.
 | 
			
		||||
With a prefix argument, visit in another window.  If there
 | 
			
		||||
is no file at point, then instead visit `default-directory'."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (dired-jump other-window
 | 
			
		||||
              (when-let ((file (magit-file-at-point)))
 | 
			
		||||
                (expand-file-name (if (file-directory-p file)
 | 
			
		||||
                                      (file-name-as-directory file)
 | 
			
		||||
                                    file)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-dired-log (&optional follow)
 | 
			
		||||
  "Show log for all marked files, or the current file."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (if-let ((topdir (magit-toplevel default-directory)))
 | 
			
		||||
      (let ((args (car (magit-log-arguments)))
 | 
			
		||||
            (files (dired-get-marked-files nil nil #'magit-file-tracked-p)))
 | 
			
		||||
        (unless files
 | 
			
		||||
          (user-error "No marked file is being tracked by Git"))
 | 
			
		||||
        (when (and follow
 | 
			
		||||
                   (not (member "--follow" args))
 | 
			
		||||
                   (not (cdr files)))
 | 
			
		||||
          (push "--follow" args))
 | 
			
		||||
        (magit-log-setup-buffer
 | 
			
		||||
         (list (or (magit-get-current-branch) "HEAD"))
 | 
			
		||||
         args
 | 
			
		||||
         (let ((default-directory topdir))
 | 
			
		||||
           (mapcar #'file-relative-name files))
 | 
			
		||||
         magit-log-buffer-file-locked))
 | 
			
		||||
    (magit--not-inside-repository-error)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-do-async-shell-command (file)
 | 
			
		||||
  "Open FILE with `dired-do-async-shell-command'.
 | 
			
		||||
Interactively, open the file at point."
 | 
			
		||||
  (interactive (list (or (magit-file-at-point)
 | 
			
		||||
                         (completing-read "Act on file: "
 | 
			
		||||
                                          (magit-list-files)))))
 | 
			
		||||
  (require 'dired-aux)
 | 
			
		||||
  (dired-do-async-shell-command
 | 
			
		||||
   (dired-read-shell-command "& on %s: " current-prefix-arg (list file))
 | 
			
		||||
   nil (list file)))
 | 
			
		||||
 | 
			
		||||
;;; Shift Selection
 | 
			
		||||
 | 
			
		||||
(defun magit--turn-on-shift-select-mode-p ()
 | 
			
		||||
  (and shift-select-mode
 | 
			
		||||
       this-command-keys-shift-translated
 | 
			
		||||
       (not mark-active)
 | 
			
		||||
       (not (eq (car-safe transient-mark-mode) 'only))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-previous-line (&optional arg try-vscroll)
 | 
			
		||||
  "Like `previous-line' but with Magit-specific shift-selection.
 | 
			
		||||
 | 
			
		||||
Magit's selection mechanism is based on the region but selects an
 | 
			
		||||
area that is larger than the region.  This causes `previous-line'
 | 
			
		||||
when invoked while holding the shift key to move up one line and
 | 
			
		||||
thereby select two lines.  When invoked inside a hunk body this
 | 
			
		||||
command does not move point on the first invocation and thereby
 | 
			
		||||
it only selects a single line.  Which inconsistency you prefer
 | 
			
		||||
is a matter of preference."
 | 
			
		||||
  (declare (interactive-only
 | 
			
		||||
            "use `forward-line' with negative argument instead."))
 | 
			
		||||
  (interactive "p\np")
 | 
			
		||||
  (unless arg (setq arg 1))
 | 
			
		||||
  (let ((stay (or (magit-diff-inside-hunk-body-p)
 | 
			
		||||
                  (magit-section-position-in-heading-p))))
 | 
			
		||||
    (if (and stay (= arg 1) (magit--turn-on-shift-select-mode-p))
 | 
			
		||||
        (push-mark nil nil t)
 | 
			
		||||
      (with-no-warnings
 | 
			
		||||
        (handle-shift-selection)
 | 
			
		||||
        (previous-line (if stay (max (1- arg) 1) arg) try-vscroll)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-next-line (&optional arg try-vscroll)
 | 
			
		||||
  "Like `next-line' but with Magit-specific shift-selection.
 | 
			
		||||
 | 
			
		||||
Magit's selection mechanism is based on the region but selects
 | 
			
		||||
an area that is larger than the region.  This causes `next-line'
 | 
			
		||||
when invoked while holding the shift key to move down one line
 | 
			
		||||
and thereby select two lines.  When invoked inside a hunk body
 | 
			
		||||
this command does not move point on the first invocation and
 | 
			
		||||
thereby it only selects a single line.  Which inconsistency you
 | 
			
		||||
prefer is a matter of preference."
 | 
			
		||||
  (declare (interactive-only forward-line))
 | 
			
		||||
  (interactive "p\np")
 | 
			
		||||
  (unless arg (setq arg 1))
 | 
			
		||||
  (let ((stay (or (magit-diff-inside-hunk-body-p)
 | 
			
		||||
                  (magit-section-position-in-heading-p))))
 | 
			
		||||
    (if (and stay (= arg 1) (magit--turn-on-shift-select-mode-p))
 | 
			
		||||
        (push-mark nil nil t)
 | 
			
		||||
      (with-no-warnings
 | 
			
		||||
        (handle-shift-selection)
 | 
			
		||||
        (next-line (if stay (max (1- arg) 1) arg) try-vscroll)))))
 | 
			
		||||
 | 
			
		||||
;;; Clean
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-clean (&optional arg)
 | 
			
		||||
  "Remove untracked files from the working tree.
 | 
			
		||||
With a prefix argument also remove ignored files,
 | 
			
		||||
with two prefix arguments remove ignored files only.
 | 
			
		||||
\n(git clean -f -d [-x|-X])"
 | 
			
		||||
  (interactive "p")
 | 
			
		||||
  (when (yes-or-no-p (format "Remove %s files? "
 | 
			
		||||
                             (pcase arg
 | 
			
		||||
                               (1 "untracked")
 | 
			
		||||
                               (4 "untracked and ignored")
 | 
			
		||||
                               (_ "ignored"))))
 | 
			
		||||
    (magit-wip-commit-before-change)
 | 
			
		||||
    (magit-run-git "clean" "-f" "-d" (pcase arg (4 "-x") (16 "-X")))))
 | 
			
		||||
 | 
			
		||||
(put 'magit-clean 'disabled t)
 | 
			
		||||
 | 
			
		||||
;;; ChangeLog
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-add-change-log-entry (&optional whoami file-name other-window)
 | 
			
		||||
  "Find change log file and add date entry and item for current change.
 | 
			
		||||
This differs from `add-change-log-entry' (which see) in that
 | 
			
		||||
it acts on the current hunk in a Magit buffer instead of on
 | 
			
		||||
a position in a file-visiting buffer."
 | 
			
		||||
  (interactive (list current-prefix-arg
 | 
			
		||||
                     (prompt-for-change-log-name)))
 | 
			
		||||
  (pcase-let ((`(,buf ,pos) (magit-diff-visit-file--noselect)))
 | 
			
		||||
    (magit--with-temp-position buf pos
 | 
			
		||||
      (let ((add-log-buffer-file-name-function
 | 
			
		||||
             (lambda ()
 | 
			
		||||
               (or magit-buffer-file-name
 | 
			
		||||
                   (buffer-file-name)))))
 | 
			
		||||
        (add-change-log-entry whoami file-name other-window)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-add-change-log-entry-other-window (&optional whoami file-name)
 | 
			
		||||
  "Find change log file in other window and add entry and item.
 | 
			
		||||
This differs from `add-change-log-entry-other-window' (which see)
 | 
			
		||||
in that it acts on the current hunk in a Magit buffer instead of
 | 
			
		||||
on a position in a file-visiting buffer."
 | 
			
		||||
  (interactive (and current-prefix-arg
 | 
			
		||||
                    (list current-prefix-arg
 | 
			
		||||
                          (prompt-for-change-log-name))))
 | 
			
		||||
  (magit-add-change-log-entry whoami file-name t))
 | 
			
		||||
 | 
			
		||||
;;; Edit Line Commit
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-edit-line-commit (&optional type)
 | 
			
		||||
  "Edit the commit that added the current line.
 | 
			
		||||
 | 
			
		||||
With a prefix argument edit the commit that removes the line,
 | 
			
		||||
if any.  The commit is determined using `git blame' and made
 | 
			
		||||
editable using `git rebase --interactive' if it is reachable
 | 
			
		||||
from `HEAD', or by checking out the commit (or a branch that
 | 
			
		||||
points at it) otherwise."
 | 
			
		||||
  (interactive (list (and current-prefix-arg 'removal)))
 | 
			
		||||
  (let* ((chunk (magit-current-blame-chunk (or type 'addition)))
 | 
			
		||||
         (rev   (oref chunk orig-rev)))
 | 
			
		||||
    (if (equal rev "0000000000000000000000000000000000000000")
 | 
			
		||||
        (message "This line has not been committed yet")
 | 
			
		||||
      (let ((rebase (magit-rev-ancestor-p rev "HEAD"))
 | 
			
		||||
            (file   (expand-file-name (oref chunk orig-file)
 | 
			
		||||
                                      (magit-toplevel))))
 | 
			
		||||
        (if rebase
 | 
			
		||||
            (let ((magit--rebase-published-symbol 'edit-published))
 | 
			
		||||
              (magit-rebase-edit-commit rev (magit-rebase-arguments)))
 | 
			
		||||
          (magit-checkout (or (magit-rev-branch rev) rev)))
 | 
			
		||||
        (unless (and buffer-file-name
 | 
			
		||||
                     (file-equal-p file buffer-file-name))
 | 
			
		||||
          (let ((blame-type (and magit-blame-mode magit-blame-type)))
 | 
			
		||||
            (if rebase
 | 
			
		||||
                (set-process-sentinel
 | 
			
		||||
                 magit-this-process
 | 
			
		||||
                 (lambda (process event)
 | 
			
		||||
                   (magit-sequencer-process-sentinel process event)
 | 
			
		||||
                   (when (eq (process-status process) 'exit)
 | 
			
		||||
                     (find-file file)
 | 
			
		||||
                     (when blame-type
 | 
			
		||||
                       (magit-blame--pre-blame-setup blame-type)
 | 
			
		||||
                       (magit-blame--run (magit-blame-arguments))))))
 | 
			
		||||
              (find-file file)
 | 
			
		||||
              (when blame-type
 | 
			
		||||
                (magit-blame--pre-blame-setup blame-type)
 | 
			
		||||
                (magit-blame--run (magit-blame-arguments))))))))))
 | 
			
		||||
 | 
			
		||||
(put 'magit-edit-line-commit 'disabled t)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-diff-edit-hunk-commit (file)
 | 
			
		||||
  "From a hunk, edit the respective commit and visit the file.
 | 
			
		||||
 | 
			
		||||
First visit the file being modified by the hunk at the correct
 | 
			
		||||
location using `magit-diff-visit-file'.  This actually visits a
 | 
			
		||||
blob.  When point is on a diff header, not within an individual
 | 
			
		||||
hunk, then this visits the blob the first hunk is about.
 | 
			
		||||
 | 
			
		||||
Then invoke `magit-edit-line-commit', which uses an interactive
 | 
			
		||||
rebase to make the commit editable, or if that is not possible
 | 
			
		||||
because the commit is not reachable from `HEAD' by checking out
 | 
			
		||||
that commit directly.  This also causes the actual worktree file
 | 
			
		||||
to be visited.
 | 
			
		||||
 | 
			
		||||
Neither the blob nor the file buffer are killed when finishing
 | 
			
		||||
the rebase.  If that is undesirable, then it might be better to
 | 
			
		||||
use `magit-rebase-edit-command' instead of this command."
 | 
			
		||||
  (interactive (list (magit-file-at-point t t)))
 | 
			
		||||
  (let ((magit-diff-visit-previous-blob nil))
 | 
			
		||||
    (with-current-buffer
 | 
			
		||||
        (magit-diff-visit-file--internal file nil #'pop-to-buffer-same-window)
 | 
			
		||||
      (magit-edit-line-commit))))
 | 
			
		||||
 | 
			
		||||
(put 'magit-diff-edit-hunk-commit 'disabled t)
 | 
			
		||||
 | 
			
		||||
;;; Reshelve
 | 
			
		||||
 | 
			
		||||
(defcustom magit-reshelve-since-committer-only nil
 | 
			
		||||
  "Whether `magit-reshelve-since' changes only the committer dates.
 | 
			
		||||
Otherwise the author dates are also changed."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-reshelve-since (rev)
 | 
			
		||||
  "Change the author and committer dates of the commits since REV.
 | 
			
		||||
 | 
			
		||||
Ask the user for the first reachable commit whose dates should
 | 
			
		||||
be changed.  Then read the new date for that commit.  The initial
 | 
			
		||||
minibuffer input and the previous history element offer good
 | 
			
		||||
values.  The next commit will be created one minute later and so
 | 
			
		||||
on.
 | 
			
		||||
 | 
			
		||||
This command is only intended for interactive use and should only
 | 
			
		||||
be used on highly rearranged and unpublished history."
 | 
			
		||||
  (interactive (list nil))
 | 
			
		||||
  (let* ((current (or (magit-get-current-branch)
 | 
			
		||||
                      (user-error "Refusing to reshelve detached head")))
 | 
			
		||||
         (backup (concat "refs/original/refs/heads/" current)))
 | 
			
		||||
    (cond
 | 
			
		||||
     ((not rev)
 | 
			
		||||
      (when (and (magit-ref-p backup)
 | 
			
		||||
                 (not (magit-y-or-n-p
 | 
			
		||||
                       (format "Backup ref %s already exists.  Override? " backup))))
 | 
			
		||||
        (user-error "Abort"))
 | 
			
		||||
      (magit-log-select 'magit-reshelve-since
 | 
			
		||||
        "Type %p on a commit to reshelve it and the commits above it,"))
 | 
			
		||||
     (t
 | 
			
		||||
      (cl-flet ((adjust (time offset)
 | 
			
		||||
                        (format-time-string
 | 
			
		||||
                         "%F %T %z"
 | 
			
		||||
                         (+ (floor time)
 | 
			
		||||
                            (* offset 60)
 | 
			
		||||
                            (- (car (decode-time time)))))))
 | 
			
		||||
        (let* ((start (concat rev "^"))
 | 
			
		||||
               (range (concat start ".." current))
 | 
			
		||||
               (time-rev (adjust (float-time (string-to-number
 | 
			
		||||
                                              (magit-rev-format "%at" start)))
 | 
			
		||||
                                 1))
 | 
			
		||||
               (time-now (adjust (float-time)
 | 
			
		||||
                                 (- (string-to-number
 | 
			
		||||
                                     (magit-git-string "rev-list" "--count"
 | 
			
		||||
                                                       range))))))
 | 
			
		||||
          (push time-rev magit--reshelve-history)
 | 
			
		||||
          (let ((date (floor
 | 
			
		||||
                       (float-time
 | 
			
		||||
                        (date-to-time
 | 
			
		||||
                         (read-string "Date for first commit: "
 | 
			
		||||
                                      time-now 'magit--reshelve-history)))))
 | 
			
		||||
                (process-environment process-environment))
 | 
			
		||||
            (push "FILTER_BRANCH_SQUELCH_WARNING=1" process-environment)
 | 
			
		||||
            (magit-with-toplevel
 | 
			
		||||
              (magit-run-git-async
 | 
			
		||||
               "filter-branch" "--force" "--env-filter"
 | 
			
		||||
               (format
 | 
			
		||||
                "case $GIT_COMMIT in %s\nesac"
 | 
			
		||||
                (mapconcat
 | 
			
		||||
                 (lambda (rev)
 | 
			
		||||
                   (prog1 (concat
 | 
			
		||||
                           (format "%s) " rev)
 | 
			
		||||
                           (and (not magit-reshelve-since-committer-only)
 | 
			
		||||
                                (format "export GIT_AUTHOR_DATE=\"%s\"; " date))
 | 
			
		||||
                           (format "export GIT_COMMITTER_DATE=\"%s\";;" date))
 | 
			
		||||
                     (cl-incf date 60)))
 | 
			
		||||
                 (magit-git-lines "rev-list" "--reverse" range)
 | 
			
		||||
                        " "))
 | 
			
		||||
               range "--"))
 | 
			
		||||
            (set-process-sentinel
 | 
			
		||||
             magit-this-process
 | 
			
		||||
             (lambda (process event)
 | 
			
		||||
               (when (memq (process-status process) '(exit signal))
 | 
			
		||||
                 (if (> (process-exit-status process) 0)
 | 
			
		||||
                     (magit-process-sentinel process event)
 | 
			
		||||
                   (process-put process 'inhibit-refresh t)
 | 
			
		||||
                   (magit-process-sentinel process event)
 | 
			
		||||
                   (magit-run-git "update-ref" "-d" backup))))))))))))
 | 
			
		||||
 | 
			
		||||
;;; Revision Stack
 | 
			
		||||
 | 
			
		||||
(defvar magit-revision-stack nil)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-pop-revision-stack-format
 | 
			
		||||
  '("[%N: %h] " "%N: %H\n   %s\n" "\\[\\([0-9]+\\)[]:]")
 | 
			
		||||
  "Control how `magit-pop-revision-stack' inserts a revision.
 | 
			
		||||
 | 
			
		||||
The command `magit-pop-revision-stack' inserts a representation
 | 
			
		||||
of the revision last pushed to the `magit-revision-stack' into
 | 
			
		||||
the current buffer.  It inserts text at point and/or near the end
 | 
			
		||||
of the buffer, and removes the consumed revision from the stack.
 | 
			
		||||
 | 
			
		||||
The entries on the stack have the format (HASH TOPLEVEL) and this
 | 
			
		||||
option has the format (POINT-FORMAT EOB-FORMAT INDEX-REGEXP), all
 | 
			
		||||
of which may be nil or a string (though either one of EOB-FORMAT
 | 
			
		||||
or POINT-FORMAT should be a string, and if INDEX-REGEXP is
 | 
			
		||||
non-nil, then the two formats should be too).
 | 
			
		||||
 | 
			
		||||
First INDEX-REGEXP is used to find the previously inserted entry,
 | 
			
		||||
by searching backward from point.  The first submatch must match
 | 
			
		||||
the index number.  That number is incremented by one, and becomes
 | 
			
		||||
the index number of the entry to be inserted.  If you don't want
 | 
			
		||||
to number the inserted revisions, then use nil for INDEX-REGEXP.
 | 
			
		||||
 | 
			
		||||
If INDEX-REGEXP is non-nil, then both POINT-FORMAT and EOB-FORMAT
 | 
			
		||||
should contain \"%N\", which is replaced with the number that was
 | 
			
		||||
determined in the previous step.
 | 
			
		||||
 | 
			
		||||
Both formats, if non-nil and after removing %N, are then expanded
 | 
			
		||||
using `git show --format=FORMAT ...' inside TOPLEVEL.
 | 
			
		||||
 | 
			
		||||
The expansion of POINT-FORMAT is inserted at point, and the
 | 
			
		||||
expansion of EOB-FORMAT is inserted at the end of the buffer (if
 | 
			
		||||
the buffer ends with a comment, then it is inserted right before
 | 
			
		||||
that)."
 | 
			
		||||
  :package-version '(magit . "2.3.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(list (choice (string :tag "Insert at point format")
 | 
			
		||||
                       (cons (string :tag "Insert at point format")
 | 
			
		||||
                             (repeat (string :tag "Argument to git show")))
 | 
			
		||||
                       (const :tag "Don't insert at point" nil))
 | 
			
		||||
               (choice (string :tag "Insert at eob format")
 | 
			
		||||
                       (cons (string :tag "Insert at eob format")
 | 
			
		||||
                             (repeat (string :tag "Argument to git show")))
 | 
			
		||||
                       (const :tag "Don't insert at eob" nil))
 | 
			
		||||
               (choice (regexp :tag "Find index regexp")
 | 
			
		||||
                       (const :tag "Don't number entries" nil))))
 | 
			
		||||
 | 
			
		||||
(defcustom magit-copy-revision-abbreviated nil
 | 
			
		||||
  "Whether to save abbreviated revision to `kill-ring' and `magit-revision-stack'."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-miscellaneous
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-pop-revision-stack (rev toplevel)
 | 
			
		||||
  "Insert a representation of a revision into the current buffer.
 | 
			
		||||
 | 
			
		||||
Pop a revision from the `magit-revision-stack' and insert it into
 | 
			
		||||
the current buffer according to `magit-pop-revision-stack-format'.
 | 
			
		||||
Revisions can be put on the stack using `magit-copy-section-value'
 | 
			
		||||
and `magit-copy-buffer-revision'.
 | 
			
		||||
 | 
			
		||||
If the stack is empty or with a prefix argument, instead read a
 | 
			
		||||
revision in the minibuffer.  By using the minibuffer history this
 | 
			
		||||
allows selecting an item which was popped earlier or to insert an
 | 
			
		||||
arbitrary reference or revision without first pushing it onto the
 | 
			
		||||
stack.
 | 
			
		||||
 | 
			
		||||
When reading the revision from the minibuffer, then it might not
 | 
			
		||||
be possible to guess the correct repository.  When this command
 | 
			
		||||
is called inside a repository (e.g. while composing a commit
 | 
			
		||||
message), then that repository is used.  Otherwise (e.g. while
 | 
			
		||||
composing an email) then the repository recorded for the top
 | 
			
		||||
element of the stack is used (even though we insert another
 | 
			
		||||
revision).  If not called inside a repository and with an empty
 | 
			
		||||
stack, or with two prefix arguments, then read the repository in
 | 
			
		||||
the minibuffer too."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (if (or current-prefix-arg (not magit-revision-stack))
 | 
			
		||||
       (let ((default-directory
 | 
			
		||||
               (or (and (not (= (prefix-numeric-value current-prefix-arg) 16))
 | 
			
		||||
                        (or (magit-toplevel)
 | 
			
		||||
                            (cadr (car magit-revision-stack))))
 | 
			
		||||
                   (magit-read-repository))))
 | 
			
		||||
         (list (magit-read-branch-or-commit "Insert revision")
 | 
			
		||||
               default-directory))
 | 
			
		||||
     (push (caar magit-revision-stack) magit-revision-history)
 | 
			
		||||
     (pop magit-revision-stack)))
 | 
			
		||||
  (if rev
 | 
			
		||||
      (pcase-let ((`(,pnt-format ,eob-format ,idx-format)
 | 
			
		||||
                   magit-pop-revision-stack-format))
 | 
			
		||||
        (let ((default-directory toplevel)
 | 
			
		||||
              (idx (and idx-format
 | 
			
		||||
                        (save-excursion
 | 
			
		||||
                          (if (re-search-backward idx-format nil t)
 | 
			
		||||
                              (number-to-string
 | 
			
		||||
                               (1+ (string-to-number (match-string 1))))
 | 
			
		||||
                            "1"))))
 | 
			
		||||
              pnt-args eob-args)
 | 
			
		||||
          (when (listp pnt-format)
 | 
			
		||||
            (setq pnt-args (cdr pnt-format))
 | 
			
		||||
            (setq pnt-format (car pnt-format)))
 | 
			
		||||
          (when (listp eob-format)
 | 
			
		||||
            (setq eob-args (cdr eob-format))
 | 
			
		||||
            (setq eob-format (car eob-format)))
 | 
			
		||||
          (when pnt-format
 | 
			
		||||
            (when idx-format
 | 
			
		||||
              (setq pnt-format
 | 
			
		||||
                    (replace-regexp-in-string "%N" idx pnt-format t t)))
 | 
			
		||||
            (magit-rev-insert-format pnt-format rev pnt-args)
 | 
			
		||||
            (backward-delete-char 1))
 | 
			
		||||
          (when eob-format
 | 
			
		||||
            (when idx-format
 | 
			
		||||
              (setq eob-format
 | 
			
		||||
                    (replace-regexp-in-string "%N" idx eob-format t t)))
 | 
			
		||||
            (save-excursion
 | 
			
		||||
              (goto-char (point-max))
 | 
			
		||||
              (skip-syntax-backward ">s-")
 | 
			
		||||
              (beginning-of-line)
 | 
			
		||||
              (if (and comment-start (looking-at comment-start))
 | 
			
		||||
                  (while (looking-at comment-start)
 | 
			
		||||
                    (forward-line -1))
 | 
			
		||||
                (forward-line)
 | 
			
		||||
                (unless (= (current-column) 0)
 | 
			
		||||
                  (insert ?\n)))
 | 
			
		||||
              (insert ?\n)
 | 
			
		||||
              (magit-rev-insert-format eob-format rev eob-args)
 | 
			
		||||
              (backward-delete-char 1)))))
 | 
			
		||||
    (user-error "Revision stack is empty")))
 | 
			
		||||
 | 
			
		||||
(define-key git-commit-mode-map
 | 
			
		||||
  (kbd "C-c C-w") 'magit-pop-revision-stack)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-copy-section-value ()
 | 
			
		||||
  "Save the value of the current section for later use.
 | 
			
		||||
 | 
			
		||||
Save the section value to the `kill-ring', and, provided that
 | 
			
		||||
the current section is a commit, branch, or tag section, push
 | 
			
		||||
the (referenced) revision to the `magit-revision-stack' for use
 | 
			
		||||
with `magit-pop-revision-stack'.
 | 
			
		||||
 | 
			
		||||
When `magit-copy-revision-abbreviated' is non-nil, save the
 | 
			
		||||
abbreviated revision to the `kill-ring' and the
 | 
			
		||||
`magit-revision-stack'.
 | 
			
		||||
 | 
			
		||||
When the current section is a branch or a tag, and a prefix
 | 
			
		||||
argument is used, then save the revision at its tip to the
 | 
			
		||||
`kill-ring' instead of the reference name.
 | 
			
		||||
 | 
			
		||||
When the region is active, then save that to the `kill-ring',
 | 
			
		||||
like `kill-ring-save' would, instead of behaving as described
 | 
			
		||||
above.  If a prefix argument is used and the region is within a
 | 
			
		||||
hunk, strip the outer diff marker column."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (cond
 | 
			
		||||
   ((and current-prefix-arg
 | 
			
		||||
         (magit-section-internal-region-p)
 | 
			
		||||
         (magit-section-match 'hunk))
 | 
			
		||||
    (kill-new (replace-regexp-in-string
 | 
			
		||||
               "^[ \\+\\-]" ""
 | 
			
		||||
               (buffer-substring-no-properties
 | 
			
		||||
                (region-beginning) (region-end))))
 | 
			
		||||
    (deactivate-mark))
 | 
			
		||||
   ((use-region-p)
 | 
			
		||||
    (call-interactively #'copy-region-as-kill))
 | 
			
		||||
   (t
 | 
			
		||||
    (when-let ((section (magit-current-section))
 | 
			
		||||
               (value (oref section value)))
 | 
			
		||||
      (magit-section-case
 | 
			
		||||
        ((branch commit module-commit tag)
 | 
			
		||||
         (let ((default-directory default-directory) ref)
 | 
			
		||||
           (magit-section-case
 | 
			
		||||
             ((branch tag)
 | 
			
		||||
              (setq ref value))
 | 
			
		||||
             (module-commit
 | 
			
		||||
              (setq default-directory
 | 
			
		||||
                    (file-name-as-directory
 | 
			
		||||
                     (expand-file-name (magit-section-parent-value section)
 | 
			
		||||
                                       (magit-toplevel))))))
 | 
			
		||||
           (setq value (magit-rev-parse
 | 
			
		||||
                        (and magit-copy-revision-abbreviated "--short")
 | 
			
		||||
                        value))
 | 
			
		||||
           (push (list value default-directory) magit-revision-stack)
 | 
			
		||||
           (kill-new (message "%s" (or (and current-prefix-arg ref)
 | 
			
		||||
                                       value)))))
 | 
			
		||||
        (t (kill-new (message "%s" value))))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-copy-buffer-revision ()
 | 
			
		||||
  "Save the revision of the current buffer for later use.
 | 
			
		||||
 | 
			
		||||
Save the revision shown in the current buffer to the `kill-ring'
 | 
			
		||||
and push it to the `magit-revision-stack'.
 | 
			
		||||
 | 
			
		||||
This command is mainly intended for use in `magit-revision-mode'
 | 
			
		||||
buffers, the only buffers where it is always unambiguous exactly
 | 
			
		||||
which revision should be saved.
 | 
			
		||||
 | 
			
		||||
Most other Magit buffers usually show more than one revision, in
 | 
			
		||||
some way or another, so this command has to select one of them,
 | 
			
		||||
and that choice might not always be the one you think would have
 | 
			
		||||
been the best pick.
 | 
			
		||||
 | 
			
		||||
In such buffers it is often more useful to save the value of
 | 
			
		||||
the current section instead, using `magit-copy-section-value'.
 | 
			
		||||
 | 
			
		||||
When the region is active, then save that to the `kill-ring',
 | 
			
		||||
like `kill-ring-save' would, instead of behaving as described
 | 
			
		||||
above.
 | 
			
		||||
 | 
			
		||||
When `magit-copy-revision-abbreviated' is non-nil, save the
 | 
			
		||||
abbreviated revision to the `kill-ring' and the
 | 
			
		||||
`magit-revision-stack'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if (use-region-p)
 | 
			
		||||
      (call-interactively #'copy-region-as-kill)
 | 
			
		||||
    (when-let ((rev (or magit-buffer-revision
 | 
			
		||||
                        (cl-case major-mode
 | 
			
		||||
                          (magit-diff-mode
 | 
			
		||||
                           (if (string-match "\\.\\.\\.?\\(.+\\)"
 | 
			
		||||
                                             magit-buffer-range)
 | 
			
		||||
                               (match-string 1 magit-buffer-range)
 | 
			
		||||
                             magit-buffer-range))
 | 
			
		||||
                          (magit-status-mode "HEAD")))))
 | 
			
		||||
      (when (magit-commit-p rev)
 | 
			
		||||
        (setq rev (magit-rev-parse
 | 
			
		||||
                   (and magit-copy-revision-abbreviated "--short")
 | 
			
		||||
                   rev))
 | 
			
		||||
        (push (list rev default-directory) magit-revision-stack)
 | 
			
		||||
        (kill-new (message "%s" rev))))))
 | 
			
		||||
 | 
			
		||||
;;; Miscellaneous
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-abort-dwim ()
 | 
			
		||||
  "Abort current operation.
 | 
			
		||||
Depending on the context, this will abort a merge, a rebase, a
 | 
			
		||||
patch application, a cherry-pick, a revert, or a bisect."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (cond ((magit-merge-in-progress-p)     (magit-merge-abort))
 | 
			
		||||
        ((magit-rebase-in-progress-p)    (magit-rebase-abort))
 | 
			
		||||
        ((magit-am-in-progress-p)        (magit-am-abort))
 | 
			
		||||
        ((magit-sequencer-in-progress-p) (magit-sequencer-abort))
 | 
			
		||||
        ((magit-bisect-in-progress-p)    (magit-bisect-reset))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-extras)
 | 
			
		||||
;;; magit-extras.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,187 +0,0 @@
 | 
			
		||||
;;; magit-fetch.el --- download objects and refs  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements fetch commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-fetch-modules-jobs 4
 | 
			
		||||
  "Number of submodules to fetch in parallel.
 | 
			
		||||
Ignored for Git versions before v2.8.0."
 | 
			
		||||
  :package-version '(magit . "2.12.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type '(choice (const :tag "one at a time" nil) number))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-fetch "magit-fetch" nil t)
 | 
			
		||||
(transient-define-prefix magit-fetch ()
 | 
			
		||||
  "Fetch from another repository."
 | 
			
		||||
  :man-page "git-fetch"
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   ("-p" "Prune deleted branches" ("-p" "--prune"))
 | 
			
		||||
   ("-t" "Fetch all tags" ("-t" "--tags"))
 | 
			
		||||
   (7 "-u" "Fetch full history" "--unshallow")]
 | 
			
		||||
  ["Fetch from"
 | 
			
		||||
   ("p" magit-fetch-from-pushremote)
 | 
			
		||||
   ("u" magit-fetch-from-upstream)
 | 
			
		||||
   ("e" "elsewhere"        magit-fetch-other)
 | 
			
		||||
   ("a" "all remotes"      magit-fetch-all)]
 | 
			
		||||
  ["Fetch"
 | 
			
		||||
   ("o" "another branch"   magit-fetch-branch)
 | 
			
		||||
   ("r" "explicit refspec" magit-fetch-refspec)
 | 
			
		||||
   ("m" "submodules"       magit-fetch-modules)]
 | 
			
		||||
  ["Configure"
 | 
			
		||||
   ("C" "variables..." magit-branch-configure)])
 | 
			
		||||
 | 
			
		||||
(defun magit-fetch-arguments ()
 | 
			
		||||
  (transient-args 'magit-fetch))
 | 
			
		||||
 | 
			
		||||
(defun magit-git-fetch (remote args)
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "fetch" remote args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t)
 | 
			
		||||
(transient-define-suffix magit-fetch-from-pushremote (args)
 | 
			
		||||
  "Fetch from the current push-remote.
 | 
			
		||||
 | 
			
		||||
With a prefix argument or when the push-remote is either not
 | 
			
		||||
configured or unusable, then let the user first configure the
 | 
			
		||||
push-remote."
 | 
			
		||||
  :description 'magit-fetch--pushremote-description
 | 
			
		||||
  (interactive (list (magit-fetch-arguments)))
 | 
			
		||||
  (let ((remote (magit-get-push-remote)))
 | 
			
		||||
    (when (or current-prefix-arg
 | 
			
		||||
              (not (member remote (magit-list-remotes))))
 | 
			
		||||
      (let ((var (magit--push-remote-variable)))
 | 
			
		||||
        (setq remote
 | 
			
		||||
              (magit-read-remote (format "Set %s and fetch from there" var)))
 | 
			
		||||
        (magit-set remote var)))
 | 
			
		||||
    (magit-git-fetch remote args)))
 | 
			
		||||
 | 
			
		||||
(defun magit-fetch--pushremote-description ()
 | 
			
		||||
  (let* ((branch (magit-get-current-branch))
 | 
			
		||||
         (remote (magit-get-push-remote branch))
 | 
			
		||||
         (v (magit--push-remote-variable branch t)))
 | 
			
		||||
    (cond
 | 
			
		||||
     ((member remote (magit-list-remotes)) remote)
 | 
			
		||||
     (remote
 | 
			
		||||
      (format "%s, replacing invalid" v))
 | 
			
		||||
     (t
 | 
			
		||||
      (format "%s, setting that" v)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-fetch-from-upstream "magit-fetch" nil t)
 | 
			
		||||
(transient-define-suffix magit-fetch-from-upstream (remote args)
 | 
			
		||||
  "Fetch from the \"current\" remote, usually the upstream.
 | 
			
		||||
 | 
			
		||||
If the upstream is configured for the current branch and names
 | 
			
		||||
an existing remote, then use that.  Otherwise try to use another
 | 
			
		||||
remote: If only a single remote is configured, then use that.
 | 
			
		||||
Otherwise if a remote named \"origin\" exists, then use that.
 | 
			
		||||
 | 
			
		||||
If no remote can be determined, then this command is not available
 | 
			
		||||
from the `magit-fetch' transient prefix and invoking it directly
 | 
			
		||||
results in an error."
 | 
			
		||||
  :if          (lambda () (magit-get-current-remote t))
 | 
			
		||||
  :description (lambda () (magit-get-current-remote t))
 | 
			
		||||
  (interactive (list (magit-get-current-remote t)
 | 
			
		||||
                     (magit-fetch-arguments)))
 | 
			
		||||
  (unless remote
 | 
			
		||||
    (error "The \"current\" remote could not be determined"))
 | 
			
		||||
  (magit-git-fetch remote args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-other (remote args)
 | 
			
		||||
  "Fetch from another repository."
 | 
			
		||||
  (interactive (list (magit-read-remote "Fetch remote")
 | 
			
		||||
                     (magit-fetch-arguments)))
 | 
			
		||||
  (magit-git-fetch remote args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-branch (remote branch args)
 | 
			
		||||
  "Fetch a BRANCH from a REMOTE."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((remote (magit-read-remote-or-url "Fetch from remote or url")))
 | 
			
		||||
     (list remote
 | 
			
		||||
           (magit-read-remote-branch "Fetch branch" remote)
 | 
			
		||||
           (magit-fetch-arguments))))
 | 
			
		||||
  (magit-git-fetch remote (cons branch args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-refspec (remote refspec args)
 | 
			
		||||
  "Fetch a REFSPEC from a REMOTE."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((remote (magit-read-remote-or-url "Fetch from remote or url")))
 | 
			
		||||
     (list remote
 | 
			
		||||
           (magit-read-refspec "Fetch using refspec" remote)
 | 
			
		||||
           (magit-fetch-arguments))))
 | 
			
		||||
  (magit-git-fetch remote (cons refspec args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-all (args)
 | 
			
		||||
  "Fetch from all remotes."
 | 
			
		||||
  (interactive (list (magit-fetch-arguments)))
 | 
			
		||||
  (magit-git-fetch nil (cons "--all" args)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-all-prune ()
 | 
			
		||||
  "Fetch from all remotes, and prune.
 | 
			
		||||
Prune remote tracking branches for branches that have been
 | 
			
		||||
removed on the respective remote."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "remote" "update" "--prune"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-all-no-prune ()
 | 
			
		||||
  "Fetch from all remotes."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "remote" "update"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-fetch-modules (&optional all)
 | 
			
		||||
  "Fetch all submodules.
 | 
			
		||||
 | 
			
		||||
Option `magit-fetch-modules-jobs' controls how many submodules
 | 
			
		||||
are being fetched in parallel.  Also fetch the super-repository,
 | 
			
		||||
because `git-fetch' does not support not doing that.  With a
 | 
			
		||||
prefix argument fetch all remotes."
 | 
			
		||||
  (interactive "P")
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git-async
 | 
			
		||||
     "fetch" "--verbose" "--recurse-submodules"
 | 
			
		||||
     (and magit-fetch-modules-jobs
 | 
			
		||||
          (version<= "2.8.0" (magit-git-version))
 | 
			
		||||
          (list "-j" (number-to-string magit-fetch-modules-jobs)))
 | 
			
		||||
     (and all "--all"))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-fetch)
 | 
			
		||||
;;; magit-fetch.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,551 +0,0 @@
 | 
			
		||||
;;; magit-files.el --- finding files  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements support for finding blobs, staged files,
 | 
			
		||||
;; and Git configuration files.  It also implements modes useful in
 | 
			
		||||
;; buffers visiting files and blobs, and the commands used by those
 | 
			
		||||
;; modes.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Find Blob
 | 
			
		||||
 | 
			
		||||
(defvar magit-find-file-hook nil)
 | 
			
		||||
(add-hook 'magit-find-file-hook #'magit-blob-mode)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-find-file (rev file)
 | 
			
		||||
  "View FILE from REV.
 | 
			
		||||
Switch to a buffer visiting blob REV:FILE, creating one if none
 | 
			
		||||
already exists.  If prior to calling this command the current
 | 
			
		||||
buffer and/or cursor position is about the same file, then go
 | 
			
		||||
to the line and column corresponding to that location."
 | 
			
		||||
  (interactive (magit-find-file-read-args "Find file"))
 | 
			
		||||
  (magit-find-file--internal rev file #'pop-to-buffer-same-window))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-find-file-other-window (rev file)
 | 
			
		||||
  "View FILE from REV, in another window.
 | 
			
		||||
Switch to a buffer visiting blob REV:FILE, creating one if none
 | 
			
		||||
already exists.  If prior to calling this command the current
 | 
			
		||||
buffer and/or cursor position is about the same file, then go to
 | 
			
		||||
the line and column corresponding to that location."
 | 
			
		||||
  (interactive (magit-find-file-read-args "Find file in other window"))
 | 
			
		||||
  (magit-find-file--internal rev file #'switch-to-buffer-other-window))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-find-file-other-frame (rev file)
 | 
			
		||||
  "View FILE from REV, in another frame.
 | 
			
		||||
Switch to a buffer visiting blob REV:FILE, creating one if none
 | 
			
		||||
already exists.  If prior to calling this command the current
 | 
			
		||||
buffer and/or cursor position is about the same file, then go to
 | 
			
		||||
the line and column corresponding to that location."
 | 
			
		||||
  (interactive (magit-find-file-read-args "Find file in other frame"))
 | 
			
		||||
  (magit-find-file--internal rev file #'switch-to-buffer-other-frame))
 | 
			
		||||
 | 
			
		||||
(defun magit-find-file-read-args (prompt)
 | 
			
		||||
  (let ((pseudo-revs '("{worktree}" "{index}")))
 | 
			
		||||
    (if-let ((rev (magit-completing-read "Find file from revision"
 | 
			
		||||
                                         (append pseudo-revs
 | 
			
		||||
                                                 (magit-list-refnames nil t))
 | 
			
		||||
                                         nil nil nil 'magit-revision-history
 | 
			
		||||
                                         (or (magit-branch-or-commit-at-point)
 | 
			
		||||
                                             (magit-get-current-branch)))))
 | 
			
		||||
        (list rev (magit-read-file-from-rev (if (member rev pseudo-revs)
 | 
			
		||||
                                                "HEAD"
 | 
			
		||||
                                              rev)
 | 
			
		||||
                                            prompt))
 | 
			
		||||
      (user-error "Nothing selected"))))
 | 
			
		||||
 | 
			
		||||
(defun magit-find-file--internal (rev file fn)
 | 
			
		||||
  (let ((buf (magit-find-file-noselect rev file))
 | 
			
		||||
        line col)
 | 
			
		||||
    (when-let ((visited-file (magit-file-relative-name)))
 | 
			
		||||
      (setq line (line-number-at-pos))
 | 
			
		||||
      (setq col (current-column))
 | 
			
		||||
      (cond
 | 
			
		||||
       ((not (equal visited-file file)))
 | 
			
		||||
       ((equal magit-buffer-revision rev))
 | 
			
		||||
       ((equal rev "{worktree}")
 | 
			
		||||
        (setq line (magit-diff-visit--offset file magit-buffer-revision line)))
 | 
			
		||||
       ((equal rev "{index}")
 | 
			
		||||
        (setq line (magit-diff-visit--offset file nil line)))
 | 
			
		||||
       (magit-buffer-revision
 | 
			
		||||
        (setq line (magit-diff-visit--offset
 | 
			
		||||
                    file (concat magit-buffer-revision ".." rev) line)))
 | 
			
		||||
       (t
 | 
			
		||||
        (setq line (magit-diff-visit--offset file (list "-R" rev) line)))))
 | 
			
		||||
    (funcall fn buf)
 | 
			
		||||
    (when line
 | 
			
		||||
      (with-current-buffer buf
 | 
			
		||||
        (widen)
 | 
			
		||||
        (goto-char (point-min))
 | 
			
		||||
        (forward-line (1- line))
 | 
			
		||||
        (move-to-column col)))
 | 
			
		||||
    buf))
 | 
			
		||||
 | 
			
		||||
(defun magit-find-file-noselect (rev file)
 | 
			
		||||
  "Read FILE from REV into a buffer and return the buffer.
 | 
			
		||||
REV is a revision or one of \"{worktree}\" or \"{index}\".
 | 
			
		||||
FILE must be relative to the top directory of the repository."
 | 
			
		||||
  (magit-find-file-noselect-1 rev file))
 | 
			
		||||
 | 
			
		||||
(defun magit-find-file-noselect-1 (rev file &optional revert)
 | 
			
		||||
  "Read FILE from REV into a buffer and return the buffer.
 | 
			
		||||
REV is a revision or one of \"{worktree}\" or \"{index}\".
 | 
			
		||||
FILE must be relative to the top directory of the repository.
 | 
			
		||||
Non-nil REVERT means to revert the buffer.  If `ask-revert',
 | 
			
		||||
then only after asking.  A non-nil value for REVERT is ignored if REV is
 | 
			
		||||
\"{worktree}\"."
 | 
			
		||||
  (if (equal rev "{worktree}")
 | 
			
		||||
      (find-file-noselect (expand-file-name file (magit-toplevel)))
 | 
			
		||||
    (let ((topdir (magit-toplevel)))
 | 
			
		||||
      (when (file-name-absolute-p file)
 | 
			
		||||
        (setq file (file-relative-name file topdir)))
 | 
			
		||||
      (with-current-buffer (magit-get-revision-buffer-create rev file)
 | 
			
		||||
        (when (or (not magit-buffer-file-name)
 | 
			
		||||
                  (if (eq revert 'ask-revert)
 | 
			
		||||
                      (y-or-n-p (format "%s already exists; revert it? "
 | 
			
		||||
                                        (buffer-name))))
 | 
			
		||||
                  revert)
 | 
			
		||||
          (setq magit-buffer-revision
 | 
			
		||||
                (if (equal rev "{index}")
 | 
			
		||||
                    "{index}"
 | 
			
		||||
                  (magit-rev-format "%H" rev)))
 | 
			
		||||
          (setq magit-buffer-refname rev)
 | 
			
		||||
          (setq magit-buffer-file-name (expand-file-name file topdir))
 | 
			
		||||
          (setq default-directory
 | 
			
		||||
                (let ((dir (file-name-directory magit-buffer-file-name)))
 | 
			
		||||
                  (if (file-exists-p dir) dir topdir)))
 | 
			
		||||
          (setq-local revert-buffer-function #'magit-revert-rev-file-buffer)
 | 
			
		||||
          (revert-buffer t t)
 | 
			
		||||
          (run-hooks (if (equal rev "{index}")
 | 
			
		||||
                         'magit-find-index-hook
 | 
			
		||||
                       'magit-find-file-hook)))
 | 
			
		||||
        (current-buffer)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-get-revision-buffer-create (rev file)
 | 
			
		||||
  (magit-get-revision-buffer rev file t))
 | 
			
		||||
 | 
			
		||||
(defun magit-get-revision-buffer (rev file &optional create)
 | 
			
		||||
  (funcall (if create 'get-buffer-create 'get-buffer)
 | 
			
		||||
           (format "%s.~%s~" file (subst-char-in-string ?/ ?_ rev))))
 | 
			
		||||
 | 
			
		||||
(defun magit-revert-rev-file-buffer (_ignore-auto noconfirm)
 | 
			
		||||
  (when (or noconfirm
 | 
			
		||||
            (and (not (buffer-modified-p))
 | 
			
		||||
                 (catch 'found
 | 
			
		||||
                   (dolist (regexp revert-without-query)
 | 
			
		||||
                     (when (string-match regexp magit-buffer-file-name)
 | 
			
		||||
                       (throw 'found t)))))
 | 
			
		||||
            (yes-or-no-p (format "Revert buffer from Git %s? "
 | 
			
		||||
                                 (if (equal magit-buffer-refname "{index}")
 | 
			
		||||
                                     "index"
 | 
			
		||||
                                   (concat "revision " magit-buffer-refname)))))
 | 
			
		||||
    (let* ((inhibit-read-only t)
 | 
			
		||||
           (default-directory (magit-toplevel))
 | 
			
		||||
           (file (file-relative-name magit-buffer-file-name))
 | 
			
		||||
           (coding-system-for-read (or coding-system-for-read 'undecided)))
 | 
			
		||||
      (erase-buffer)
 | 
			
		||||
      (magit-git-insert "cat-file" "-p"
 | 
			
		||||
                        (if (equal magit-buffer-refname "{index}")
 | 
			
		||||
                            (concat ":" file)
 | 
			
		||||
                          (concat magit-buffer-refname ":" file)))
 | 
			
		||||
      (setq buffer-file-coding-system last-coding-system-used))
 | 
			
		||||
    (let ((buffer-file-name magit-buffer-file-name)
 | 
			
		||||
          (after-change-major-mode-hook
 | 
			
		||||
           (remq 'global-diff-hl-mode-enable-in-buffers
 | 
			
		||||
                 after-change-major-mode-hook)))
 | 
			
		||||
      (normal-mode t))
 | 
			
		||||
    (setq buffer-read-only t)
 | 
			
		||||
    (set-buffer-modified-p nil)
 | 
			
		||||
    (goto-char (point-min))))
 | 
			
		||||
 | 
			
		||||
;;; Find Index
 | 
			
		||||
 | 
			
		||||
(defvar magit-find-index-hook nil)
 | 
			
		||||
 | 
			
		||||
(defun magit-find-file-index-noselect (file &optional revert)
 | 
			
		||||
  "Read FILE from the index into a buffer and return the buffer.
 | 
			
		||||
FILE must to be relative to the top directory of the repository."
 | 
			
		||||
  (magit-find-file-noselect-1 "{index}" file (or revert 'ask-revert)))
 | 
			
		||||
 | 
			
		||||
(defun magit-update-index ()
 | 
			
		||||
  "Update the index with the contents of the current buffer.
 | 
			
		||||
The current buffer has to be visiting a file in the index, which
 | 
			
		||||
is done using `magit-find-index-noselect'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (let ((file (magit-file-relative-name)))
 | 
			
		||||
    (unless (equal magit-buffer-refname "{index}")
 | 
			
		||||
      (user-error "%s isn't visiting the index" file))
 | 
			
		||||
    (if (y-or-n-p (format "Update index with contents of %s" (buffer-name)))
 | 
			
		||||
        (let ((index (make-temp-file "index"))
 | 
			
		||||
              (buffer (current-buffer)))
 | 
			
		||||
          (when magit-wip-before-change-mode
 | 
			
		||||
            (magit-wip-commit-before-change (list file) " before un-/stage"))
 | 
			
		||||
          (let ((coding-system-for-write buffer-file-coding-system))
 | 
			
		||||
            (with-temp-file index
 | 
			
		||||
              (insert-buffer-substring buffer)))
 | 
			
		||||
          (magit-with-toplevel
 | 
			
		||||
            (magit-call-git "update-index" "--cacheinfo"
 | 
			
		||||
                            (substring (magit-git-string "ls-files" "-s" file)
 | 
			
		||||
                                       0 6)
 | 
			
		||||
                            (magit-git-string "hash-object" "-t" "blob" "-w"
 | 
			
		||||
                                              (concat "--path=" file)
 | 
			
		||||
                                              "--" index)
 | 
			
		||||
                            file))
 | 
			
		||||
          (set-buffer-modified-p nil)
 | 
			
		||||
          (when magit-wip-after-apply-mode
 | 
			
		||||
            (magit-wip-commit-after-apply (list file) " after un-/stage")))
 | 
			
		||||
      (message "Abort")))
 | 
			
		||||
  (--when-let (magit-get-mode-buffer 'magit-status-mode)
 | 
			
		||||
    (with-current-buffer it (magit-refresh)))
 | 
			
		||||
  t)
 | 
			
		||||
 | 
			
		||||
;;; Find Config File
 | 
			
		||||
 | 
			
		||||
(defun magit-find-git-config-file (filename &optional wildcards)
 | 
			
		||||
  "Edit a file located in the current repository's git directory.
 | 
			
		||||
 | 
			
		||||
When \".git\", located at the root of the working tree, is a
 | 
			
		||||
regular file, then that makes it cumbersome to open a file
 | 
			
		||||
located in the actual git directory.
 | 
			
		||||
 | 
			
		||||
This command is like `find-file', except that it temporarily
 | 
			
		||||
binds `default-directory' to the actual git directory, while
 | 
			
		||||
reading the FILENAME."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((default-directory (magit-git-dir)))
 | 
			
		||||
     (find-file-read-args "Find file: "
 | 
			
		||||
                          (confirm-nonexistent-file-or-buffer))))
 | 
			
		||||
  (find-file filename wildcards))
 | 
			
		||||
 | 
			
		||||
(defun magit-find-git-config-file-other-window (filename &optional wildcards)
 | 
			
		||||
  "Edit a file located in the current repository's git directory, in another window.
 | 
			
		||||
 | 
			
		||||
When \".git\", located at the root of the working tree, is a
 | 
			
		||||
regular file, then that makes it cumbersome to open a file
 | 
			
		||||
located in the actual git directory.
 | 
			
		||||
 | 
			
		||||
This command is like `find-file-other-window', except that it
 | 
			
		||||
temporarily binds `default-directory' to the actual git
 | 
			
		||||
directory, while reading the FILENAME."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((default-directory (magit-git-dir)))
 | 
			
		||||
     (find-file-read-args "Find file in other window: "
 | 
			
		||||
                          (confirm-nonexistent-file-or-buffer))))
 | 
			
		||||
  (find-file-other-window filename wildcards))
 | 
			
		||||
 | 
			
		||||
(defun magit-find-git-config-file-other-frame (filename &optional wildcards)
 | 
			
		||||
  "Edit a file located in the current repository's git directory, in another frame.
 | 
			
		||||
 | 
			
		||||
When \".git\", located at the root of the working tree, is a
 | 
			
		||||
regular file, then that makes it cumbersome to open a file
 | 
			
		||||
located in the actual git directory.
 | 
			
		||||
 | 
			
		||||
This command is like `find-file-other-frame', except that it
 | 
			
		||||
temporarily binds `default-directory' to the actual git
 | 
			
		||||
directory, while reading the FILENAME."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((default-directory (magit-git-dir)))
 | 
			
		||||
     (find-file-read-args "Find file in other frame: "
 | 
			
		||||
                          (confirm-nonexistent-file-or-buffer))))
 | 
			
		||||
  (find-file-other-frame filename wildcards))
 | 
			
		||||
 | 
			
		||||
;;; File Mode
 | 
			
		||||
 | 
			
		||||
(defvar magit-file-mode-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map "\C-xg"    'magit-status)
 | 
			
		||||
    (define-key map "\C-x\M-g" 'magit-dispatch)
 | 
			
		||||
    (define-key map "\C-c\M-g" 'magit-file-dispatch)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for `magit-file-mode'.")
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-file-dispatch "magit" nil t)
 | 
			
		||||
(transient-define-prefix magit-file-dispatch ()
 | 
			
		||||
  "Invoke a Magit command that acts on the visited file."
 | 
			
		||||
  :info-manual "(magit) Minor Mode for Buffers Visiting Files"
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   [("s" "Stage"      magit-stage-file)
 | 
			
		||||
    ("u" "Unstage"    magit-unstage-file)
 | 
			
		||||
    ("c" "Commit"     magit-commit)
 | 
			
		||||
    ("e" "Edit line"  magit-edit-line-commit)]
 | 
			
		||||
   [("D" "Diff..."    magit-diff)
 | 
			
		||||
    ("d" "Diff"       magit-diff-buffer-file)
 | 
			
		||||
    ("g" "Status"     magit-status-here)]
 | 
			
		||||
   [("L" "Log..."     magit-log)
 | 
			
		||||
    ("l" "Log"        magit-log-buffer-file)
 | 
			
		||||
    ("t" "Trace"      magit-log-trace-definition)]
 | 
			
		||||
   [("B" "Blame..."   magit-blame)
 | 
			
		||||
    ("b" "Blame"      magit-blame-addition)
 | 
			
		||||
    ("r" "...removal" magit-blame-removal)
 | 
			
		||||
    ("f" "...reverse" magit-blame-reverse)
 | 
			
		||||
    ("m" "Blame echo" magit-blame-echo)
 | 
			
		||||
    ("q" "Quit blame" magit-blame-quit)]
 | 
			
		||||
   [("p" "Prev blob"  magit-blob-previous)
 | 
			
		||||
    ("n" "Next blob"  magit-blob-next)
 | 
			
		||||
    ("v" "Goto blob"  magit-find-file)
 | 
			
		||||
    ("V" "Goto file"  magit-blob-visit-file)]
 | 
			
		||||
   [(5 "C-c r" "Rename file"   magit-file-rename)
 | 
			
		||||
    (5 "C-c d" "Delete file"   magit-file-delete)
 | 
			
		||||
    (5 "C-c u" "Untrack file"  magit-file-untrack)
 | 
			
		||||
    (5 "C-c c" "Checkout file" magit-file-checkout)]])
 | 
			
		||||
 | 
			
		||||
(defvar magit-file-mode-lighter "")
 | 
			
		||||
 | 
			
		||||
(define-minor-mode magit-file-mode
 | 
			
		||||
  "Enable some Magit features in a file-visiting buffer.
 | 
			
		||||
 | 
			
		||||
Currently this only adds the following key bindings.
 | 
			
		||||
\n\\{magit-file-mode-map}"
 | 
			
		||||
  :package-version '(magit . "2.2.0")
 | 
			
		||||
  :lighter magit-file-mode-lighter
 | 
			
		||||
  :keymap  magit-file-mode-map)
 | 
			
		||||
 | 
			
		||||
(defun magit-file-mode-turn-on ()
 | 
			
		||||
  (and buffer-file-name
 | 
			
		||||
       (magit-inside-worktree-p t)
 | 
			
		||||
       (magit-file-mode)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(define-globalized-minor-mode global-magit-file-mode
 | 
			
		||||
  magit-file-mode magit-file-mode-turn-on
 | 
			
		||||
  :package-version '(magit . "2.13.0")
 | 
			
		||||
  :link '(info-link "(magit)Minor Mode for Buffers Visiting Files")
 | 
			
		||||
  :group 'magit-essentials
 | 
			
		||||
  :group 'magit-modes
 | 
			
		||||
  :init-value t)
 | 
			
		||||
;; Unfortunately `:init-value t' only sets the value of the mode
 | 
			
		||||
;; variable but does not cause the mode function to be called, and we
 | 
			
		||||
;; cannot use `:initialize' to call that explicitly because the option
 | 
			
		||||
;; is defined before the functions, so we have to do it here.
 | 
			
		||||
(cl-eval-when (load eval)
 | 
			
		||||
  (when global-magit-file-mode
 | 
			
		||||
    (global-magit-file-mode 1)))
 | 
			
		||||
 | 
			
		||||
;;; Blob Mode
 | 
			
		||||
 | 
			
		||||
(defvar magit-blob-mode-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map "p" 'magit-blob-previous)
 | 
			
		||||
    (define-key map "n" 'magit-blob-next)
 | 
			
		||||
    (define-key map "b" 'magit-blame-addition)
 | 
			
		||||
    (define-key map "r" 'magit-blame-removal)
 | 
			
		||||
    (define-key map "f" 'magit-blame-reverse)
 | 
			
		||||
    (define-key map "q" 'magit-kill-this-buffer)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for `magit-blob-mode'.")
 | 
			
		||||
 | 
			
		||||
(define-minor-mode magit-blob-mode
 | 
			
		||||
  "Enable some Magit features in blob-visiting buffers.
 | 
			
		||||
 | 
			
		||||
Currently this only adds the following key bindings.
 | 
			
		||||
\n\\{magit-blob-mode-map}"
 | 
			
		||||
  :package-version '(magit . "2.3.0"))
 | 
			
		||||
 | 
			
		||||
(defun magit-blob-next ()
 | 
			
		||||
  "Visit the next blob which modified the current file."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if magit-buffer-file-name
 | 
			
		||||
      (magit-blob-visit (or (magit-blob-successor magit-buffer-revision
 | 
			
		||||
                                                  magit-buffer-file-name)
 | 
			
		||||
                            magit-buffer-file-name))
 | 
			
		||||
    (if (buffer-file-name (buffer-base-buffer))
 | 
			
		||||
        (user-error "You have reached the end of time")
 | 
			
		||||
      (user-error "Buffer isn't visiting a file or blob"))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blob-previous ()
 | 
			
		||||
  "Visit the previous blob which modified the current file."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if-let ((file (or magit-buffer-file-name
 | 
			
		||||
                     (buffer-file-name (buffer-base-buffer)))))
 | 
			
		||||
      (--if-let (magit-blob-ancestor magit-buffer-revision file)
 | 
			
		||||
          (magit-blob-visit it)
 | 
			
		||||
        (user-error "You have reached the beginning of time"))
 | 
			
		||||
    (user-error "Buffer isn't visiting a file or blob")))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-blob-visit-file ()
 | 
			
		||||
  "View the file from the worktree corresponding to the current blob.
 | 
			
		||||
When visiting a blob or the version from the index, then go to
 | 
			
		||||
the same location in the respective file in the working tree."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (if-let ((file (magit-file-relative-name)))
 | 
			
		||||
      (magit-find-file--internal "{worktree}" file #'pop-to-buffer-same-window)
 | 
			
		||||
    (user-error "Not visiting a blob")))
 | 
			
		||||
 | 
			
		||||
(defun magit-blob-visit (blob-or-file)
 | 
			
		||||
  (if (stringp blob-or-file)
 | 
			
		||||
      (find-file blob-or-file)
 | 
			
		||||
    (pcase-let ((`(,rev ,file) blob-or-file))
 | 
			
		||||
      (magit-find-file rev file)
 | 
			
		||||
      (apply #'message "%s (%s %s ago)"
 | 
			
		||||
             (magit-rev-format "%s" rev)
 | 
			
		||||
             (magit--age (magit-rev-format "%ct" rev))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blob-ancestor (rev file)
 | 
			
		||||
  (let ((lines (magit-with-toplevel
 | 
			
		||||
                 (magit-git-lines "log" "-2" "--format=%H" "--name-only"
 | 
			
		||||
                                  "--follow" (or rev "HEAD") "--" file))))
 | 
			
		||||
    (if rev (cddr lines) (butlast lines 2))))
 | 
			
		||||
 | 
			
		||||
(defun magit-blob-successor (rev file)
 | 
			
		||||
  (let ((lines (magit-with-toplevel
 | 
			
		||||
                 (magit-git-lines "log" "--format=%H" "--name-only" "--follow"
 | 
			
		||||
                                  "HEAD" "--" file))))
 | 
			
		||||
    (catch 'found
 | 
			
		||||
      (while lines
 | 
			
		||||
        (if (equal (nth 2 lines) rev)
 | 
			
		||||
            (throw 'found (list (nth 0 lines) (nth 1 lines)))
 | 
			
		||||
          (setq lines (nthcdr 2 lines)))))))
 | 
			
		||||
 | 
			
		||||
;;; File Commands
 | 
			
		||||
 | 
			
		||||
(defun magit-file-rename (file newname)
 | 
			
		||||
  "Rename the FILE to NEWNAME.
 | 
			
		||||
If FILE isn't tracked in Git, fallback to using `rename-file'."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let* ((file (magit-read-file "Rename file"))
 | 
			
		||||
          (dir (file-name-directory file))
 | 
			
		||||
          (newname (read-file-name (format "Rename %s to file: " file)
 | 
			
		||||
                                   (and dir (expand-file-name dir)))))
 | 
			
		||||
     (list (expand-file-name file (magit-toplevel))
 | 
			
		||||
           (expand-file-name newname))))
 | 
			
		||||
  (let ((oldbuf (get-file-buffer file)))
 | 
			
		||||
    (when (and oldbuf (buffer-modified-p oldbuf))
 | 
			
		||||
      (user-error "Save %s before moving it" file))
 | 
			
		||||
    (when (file-exists-p newname)
 | 
			
		||||
      (user-error "%s already exists" newname))
 | 
			
		||||
    (if (magit-file-tracked-p (magit-convert-filename-for-git file))
 | 
			
		||||
        (magit-call-git "mv"
 | 
			
		||||
                        (magit-convert-filename-for-git file)
 | 
			
		||||
                        (magit-convert-filename-for-git newname))
 | 
			
		||||
      (rename-file file newname current-prefix-arg))
 | 
			
		||||
    (when oldbuf
 | 
			
		||||
      (with-current-buffer oldbuf
 | 
			
		||||
        (let ((buffer-read-only buffer-read-only))
 | 
			
		||||
          (set-visited-file-name newname nil t))
 | 
			
		||||
        (if (fboundp 'vc-refresh-state)
 | 
			
		||||
            (vc-refresh-state)
 | 
			
		||||
          (with-no-warnings
 | 
			
		||||
            (vc-find-file-hook))))))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
(defun magit-file-untrack (files &optional force)
 | 
			
		||||
  "Untrack the selected FILES or one file read in the minibuffer.
 | 
			
		||||
 | 
			
		||||
With a prefix argument FORCE do so even when the files have
 | 
			
		||||
staged as well as unstaged changes."
 | 
			
		||||
  (interactive (list (or (--if-let (magit-region-values 'file t)
 | 
			
		||||
                             (progn
 | 
			
		||||
                               (unless (magit-file-tracked-p (car it))
 | 
			
		||||
                                 (user-error "Already untracked"))
 | 
			
		||||
                               (magit-confirm-files 'untrack it "Untrack"))
 | 
			
		||||
                           (list (magit-read-tracked-file "Untrack file"))))
 | 
			
		||||
                     current-prefix-arg))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git "rm" "--cached" (and force "--force") "--" files)))
 | 
			
		||||
 | 
			
		||||
(defun magit-file-delete (files &optional force)
 | 
			
		||||
  "Delete the selected FILES or one file read in the minibuffer.
 | 
			
		||||
 | 
			
		||||
With a prefix argument FORCE do so even when the files have
 | 
			
		||||
uncommitted changes.  When the files aren't being tracked in
 | 
			
		||||
Git, then fallback to using `delete-file'."
 | 
			
		||||
  (interactive (list (--if-let (magit-region-values 'file t)
 | 
			
		||||
                         (magit-confirm-files 'delete it "Delete")
 | 
			
		||||
                       (list (magit-read-file "Delete file")))
 | 
			
		||||
                     current-prefix-arg))
 | 
			
		||||
  (if (magit-file-tracked-p (car files))
 | 
			
		||||
      (magit-call-git "rm" (and force "--force") "--" files)
 | 
			
		||||
    (let ((topdir (magit-toplevel)))
 | 
			
		||||
      (dolist (file files)
 | 
			
		||||
        (delete-file (expand-file-name file topdir) t))))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-file-checkout (rev file)
 | 
			
		||||
  "Checkout FILE from REV."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((rev (magit-read-branch-or-commit
 | 
			
		||||
               "Checkout from revision" magit-buffer-revision)))
 | 
			
		||||
     (list rev (magit-read-file-from-rev rev "Checkout file"))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git "checkout" rev "--" file)))
 | 
			
		||||
 | 
			
		||||
;;; Read File
 | 
			
		||||
 | 
			
		||||
(defvar magit-read-file-hist nil)
 | 
			
		||||
 | 
			
		||||
(defun magit-read-file-from-rev (rev prompt &optional default)
 | 
			
		||||
  (let ((files (magit-revision-files rev)))
 | 
			
		||||
    (magit-completing-read
 | 
			
		||||
     prompt files nil t nil 'magit-read-file-hist
 | 
			
		||||
     (car (member (or default (magit-current-file)) files)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-read-file (prompt &optional tracked-only)
 | 
			
		||||
  (let ((choices (nconc (magit-list-files)
 | 
			
		||||
                        (unless tracked-only (magit-untracked-files)))))
 | 
			
		||||
    (magit-completing-read
 | 
			
		||||
     prompt choices nil t nil nil
 | 
			
		||||
     (car (member (or (magit-section-value-if '(file submodule))
 | 
			
		||||
                      (magit-file-relative-name nil tracked-only))
 | 
			
		||||
                  choices)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-read-tracked-file (prompt)
 | 
			
		||||
  (magit-read-file prompt t))
 | 
			
		||||
 | 
			
		||||
(defun magit-read-file-choice (prompt files &optional error default)
 | 
			
		||||
  "Read file from FILES.
 | 
			
		||||
 | 
			
		||||
If FILES has only one member, return that instead of prompting.
 | 
			
		||||
If FILES has no members, give a user error.  ERROR can be given
 | 
			
		||||
to provide a more informative error.
 | 
			
		||||
 | 
			
		||||
If DEFAULT is non-nil, use this as the default value instead of
 | 
			
		||||
`magit-current-file'."
 | 
			
		||||
  (pcase (length files)
 | 
			
		||||
    (0 (user-error (or error "No file choices")))
 | 
			
		||||
    (1 (car files))
 | 
			
		||||
    (_ (magit-completing-read
 | 
			
		||||
        prompt files nil t nil 'magit-read-file-hist
 | 
			
		||||
        (car (member (or default (magit-current-file)) files))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-read-changed-file (rev-or-range prompt &optional default)
 | 
			
		||||
  (magit-read-file-choice
 | 
			
		||||
   prompt
 | 
			
		||||
   (magit-changed-files rev-or-range)
 | 
			
		||||
   default
 | 
			
		||||
   (concat "No file changed in " rev-or-range)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-files)
 | 
			
		||||
;;; magit-files.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,197 +0,0 @@
 | 
			
		||||
;;; magit-gitignore.el --- intentionally untracked files  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements gitignore commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Transient
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-gitignore "magit-gitignore" nil t)
 | 
			
		||||
(transient-define-prefix magit-gitignore ()
 | 
			
		||||
  "Instruct Git to ignore a file or pattern."
 | 
			
		||||
  :man-page "gitignore"
 | 
			
		||||
  ["Gitignore"
 | 
			
		||||
   ("t" "shared at toplevel (.gitignore)"
 | 
			
		||||
    magit-gitignore-in-topdir)
 | 
			
		||||
   ("s" "shared in subdirectory (path/to/.gitignore)"
 | 
			
		||||
    magit-gitignore-in-subdir)
 | 
			
		||||
   ("p" "privately (.git/info/exclude)"
 | 
			
		||||
    magit-gitignore-in-gitdir)
 | 
			
		||||
   ("g" magit-gitignore-on-system
 | 
			
		||||
    :if (lambda () (magit-get "core.excludesfile"))
 | 
			
		||||
    :description (lambda ()
 | 
			
		||||
                   (format "privately for all repositories (%s)"
 | 
			
		||||
                           (magit-get "core.excludesfile"))))]
 | 
			
		||||
  ["Skip worktree"
 | 
			
		||||
   (7 "w" "do skip worktree"     magit-skip-worktree)
 | 
			
		||||
   (7 "W" "do not skip worktree" magit-no-skip-worktree)]
 | 
			
		||||
  ["Assume unchanged"
 | 
			
		||||
   (7 "u" "do assume unchanged"     magit-assume-unchanged)
 | 
			
		||||
   (7 "U" "do not assume unchanged" magit-no-assume-unchanged)])
 | 
			
		||||
 | 
			
		||||
;;; Gitignore Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-gitignore-in-topdir (rule)
 | 
			
		||||
  "Add the Git ignore RULE to the top-level \".gitignore\" file.
 | 
			
		||||
Since this file is tracked, it is shared with other clones of the
 | 
			
		||||
repository.  Also stage the file."
 | 
			
		||||
  (interactive (list (magit-gitignore-read-pattern)))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit--gitignore rule ".gitignore")
 | 
			
		||||
    (magit-run-git "add" ".gitignore")))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-gitignore-in-subdir (rule directory)
 | 
			
		||||
  "Add the Git ignore RULE to a \".gitignore\" file.
 | 
			
		||||
Prompted the user for a directory and add the rule to the
 | 
			
		||||
\".gitignore\" file in that directory.  Since such files are
 | 
			
		||||
tracked, they are shared with other clones of the repository.
 | 
			
		||||
Also stage the file."
 | 
			
		||||
  (interactive (list (magit-gitignore-read-pattern)
 | 
			
		||||
                     (read-directory-name "Limit rule to files in: ")))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (let ((file (expand-file-name ".gitignore" directory)))
 | 
			
		||||
      (magit--gitignore rule file)
 | 
			
		||||
      (magit-run-git "add" file))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-gitignore-in-gitdir (rule)
 | 
			
		||||
  "Add the Git ignore RULE to \"$GIT_DIR/info/exclude\".
 | 
			
		||||
Rules in that file only affects this clone of the repository."
 | 
			
		||||
  (interactive (list (magit-gitignore-read-pattern)))
 | 
			
		||||
  (magit--gitignore rule (magit-git-dir "info/exclude"))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-gitignore-on-system (rule)
 | 
			
		||||
  "Add the Git ignore RULE to the file specified by `core.excludesFile'.
 | 
			
		||||
Rules that are defined in that file affect all local repositories."
 | 
			
		||||
  (interactive (list (magit-gitignore-read-pattern)))
 | 
			
		||||
  (magit--gitignore rule
 | 
			
		||||
                    (or (magit-get "core.excludesFile")
 | 
			
		||||
                        (error "Variable `core.excludesFile' isn't set")))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
(defun magit--gitignore (rule file)
 | 
			
		||||
  (when-let ((directory (file-name-directory file)))
 | 
			
		||||
    (make-directory directory t))
 | 
			
		||||
  (with-temp-buffer
 | 
			
		||||
    (when (file-exists-p file)
 | 
			
		||||
      (insert-file-contents file))
 | 
			
		||||
    (goto-char (point-max))
 | 
			
		||||
    (unless (bolp)
 | 
			
		||||
      (insert "\n"))
 | 
			
		||||
    (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" rule))
 | 
			
		||||
    (insert "\n")
 | 
			
		||||
    (write-region nil nil file)))
 | 
			
		||||
 | 
			
		||||
(defun magit-gitignore-read-pattern ()
 | 
			
		||||
  (let* ((default (magit-current-file))
 | 
			
		||||
         (base (car magit-buffer-diff-files))
 | 
			
		||||
         (base (and base (file-directory-p base) base))
 | 
			
		||||
         (choices
 | 
			
		||||
          (delete-dups
 | 
			
		||||
           (--mapcat
 | 
			
		||||
            (cons (concat "/" it)
 | 
			
		||||
                  (when-let ((ext (file-name-extension it)))
 | 
			
		||||
                    (list (concat "/" (file-name-directory it) "*." ext)
 | 
			
		||||
                          (concat "*." ext))))
 | 
			
		||||
            (sort (nconc
 | 
			
		||||
                   (magit-untracked-files nil base)
 | 
			
		||||
                   ;; The untracked section of the status buffer lists
 | 
			
		||||
                   ;; directories containing only untracked files.
 | 
			
		||||
                   ;; Add those as candidates.
 | 
			
		||||
                   (-filter #'directory-name-p
 | 
			
		||||
                            (magit-list-files
 | 
			
		||||
                             "--other" "--exclude-standard" "--directory"
 | 
			
		||||
                             "--no-empty-directory" "--" base)))
 | 
			
		||||
                  #'string-lessp)))))
 | 
			
		||||
    (when default
 | 
			
		||||
      (setq default (concat "/" default))
 | 
			
		||||
      (unless (member default choices)
 | 
			
		||||
        (setq default (concat "*." (file-name-extension default)))
 | 
			
		||||
        (unless (member default choices)
 | 
			
		||||
          (setq default nil))))
 | 
			
		||||
    (magit-completing-read "File or pattern to ignore"
 | 
			
		||||
                           choices nil nil nil nil default)))
 | 
			
		||||
 | 
			
		||||
;;; Skip Worktree Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-skip-worktree (file)
 | 
			
		||||
  "Call \"git update-index --skip-worktree -- FILE\"."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Skip worktree for"
 | 
			
		||||
                                 (magit-with-toplevel
 | 
			
		||||
                                   (cl-set-difference
 | 
			
		||||
                                    (magit-list-files)
 | 
			
		||||
                                    (magit-skip-worktree-files))))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git "update-index" "--skip-worktree" "--" file)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-no-skip-worktree (file)
 | 
			
		||||
  "Call \"git update-index --no-skip-worktree -- FILE\"."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Do not skip worktree for"
 | 
			
		||||
                                 (magit-with-toplevel
 | 
			
		||||
                                   (magit-skip-worktree-files)))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git "update-index" "--no-skip-worktree" "--" file)))
 | 
			
		||||
 | 
			
		||||
;;; Assume Unchanged Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-assume-unchanged (file)
 | 
			
		||||
  "Call \"git update-index --assume-unchanged -- FILE\"."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Assume file to be unchanged"
 | 
			
		||||
                                 (magit-with-toplevel
 | 
			
		||||
                                   (cl-set-difference
 | 
			
		||||
                                    (magit-list-files)
 | 
			
		||||
                                    (magit-assume-unchanged-files))))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git "update-index" "--assume-unchanged" "--" file)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-no-assume-unchanged (file)
 | 
			
		||||
  "Call \"git update-index --no-assume-unchanged -- FILE\"."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-file-choice "Do not assume file to be unchanged"
 | 
			
		||||
                                 (magit-with-toplevel
 | 
			
		||||
                                   (magit-assume-unchanged-files)))))
 | 
			
		||||
  (magit-with-toplevel
 | 
			
		||||
    (magit-run-git "update-index" "--no-assume-unchanged" "--" file)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-gitignore)
 | 
			
		||||
;;; magit-gitignore.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,245 +0,0 @@
 | 
			
		||||
;;; magit-imenu.el --- Integrate Imenu in magit major modes  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Damien Cassou <damien@cassou.me>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; Emacs' major modes can facilitate navigation in their buffers by
 | 
			
		||||
;; supporting Imenu.  In such major modes, launching Imenu (M-x imenu)
 | 
			
		||||
;; makes Emacs display a list of items (e.g., function definitions in
 | 
			
		||||
;; a programming major mode).  Selecting an item from this list moves
 | 
			
		||||
;; point to this item.
 | 
			
		||||
 | 
			
		||||
;; magit-imenu.el adds Imenu support to every major mode in Magit.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
(require 'git-rebase)
 | 
			
		||||
 | 
			
		||||
;;; Core
 | 
			
		||||
 | 
			
		||||
(defun magit-imenu--index-function (entry-types menu-types)
 | 
			
		||||
  "Return an alist of imenu entries in current buffer.
 | 
			
		||||
 | 
			
		||||
ENTRY-TYPES is a list of section types to be selected through
 | 
			
		||||
`imenu'.
 | 
			
		||||
 | 
			
		||||
MENU-TYPES is a list of section types containing elements of
 | 
			
		||||
ENTRY-TYPES.  Elements of MENU-TYPES are are used to categories
 | 
			
		||||
elements of ENTRY-TYPES.
 | 
			
		||||
 | 
			
		||||
This function is used as a helper for functions set as
 | 
			
		||||
`imenu-create-index-function'."
 | 
			
		||||
  (let ((entries (make-hash-table :test 'equal)))
 | 
			
		||||
    (goto-char (point-max))
 | 
			
		||||
    (while (magit-section--backward-find
 | 
			
		||||
            (lambda ()
 | 
			
		||||
              (let* ((section (magit-current-section))
 | 
			
		||||
                     (type (oref section type))
 | 
			
		||||
                     (parent (oref section parent))
 | 
			
		||||
                     (parent-type (oref parent type)))
 | 
			
		||||
                (and (-contains-p entry-types type)
 | 
			
		||||
                     (-contains-p menu-types parent-type)))))
 | 
			
		||||
      (let* ((section (magit-current-section))
 | 
			
		||||
             (name (buffer-substring-no-properties
 | 
			
		||||
                    (line-beginning-position)
 | 
			
		||||
                    (line-end-position)))
 | 
			
		||||
             (parent (oref section parent))
 | 
			
		||||
             (parent-title (buffer-substring-no-properties
 | 
			
		||||
                            (oref parent start)
 | 
			
		||||
                            (1- (oref parent content)))))
 | 
			
		||||
        (puthash parent-title
 | 
			
		||||
                 (cons (cons name (point))
 | 
			
		||||
                       (gethash parent-title entries (list)))
 | 
			
		||||
                 entries)))
 | 
			
		||||
    (mapcar (lambda (menu-title)
 | 
			
		||||
              (cons menu-title (gethash menu-title entries)))
 | 
			
		||||
            (hash-table-keys entries))))
 | 
			
		||||
 | 
			
		||||
;;; Log mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--log-prev-index-position-function ()
 | 
			
		||||
  "Move point to previous line in current buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-prev-index-position-function'."
 | 
			
		||||
  (magit-section--backward-find
 | 
			
		||||
   (lambda ()
 | 
			
		||||
     (-contains-p '(commit stash)
 | 
			
		||||
                  (oref (magit-current-section) type)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--log-extract-index-name-function ()
 | 
			
		||||
  "Return imenu name for line at point.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-extract-index-name-function'.  Point should be at the
 | 
			
		||||
beginning of the line."
 | 
			
		||||
  (save-match-data
 | 
			
		||||
    (looking-at "\\([^ ]+\\)[ *|]+\\(.+\\)$")
 | 
			
		||||
    (format "%s: %s"
 | 
			
		||||
            (match-string-no-properties 1)
 | 
			
		||||
            (match-string-no-properties 2))))
 | 
			
		||||
 | 
			
		||||
;;; Diff mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--diff-prev-index-position-function ()
 | 
			
		||||
  "Move point to previous file line in current buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-prev-index-position-function'."
 | 
			
		||||
  (magit-section--backward-find
 | 
			
		||||
   (lambda ()
 | 
			
		||||
     (let ((section (magit-current-section)))
 | 
			
		||||
       (and (magit-file-section-p section)
 | 
			
		||||
            (not (equal (oref (oref section parent) type)
 | 
			
		||||
                        'diffstat)))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--diff-extract-index-name-function ()
 | 
			
		||||
  "Return imenu name for line at point.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-extract-index-name-function'.  Point should be at the
 | 
			
		||||
beginning of the line."
 | 
			
		||||
  (buffer-substring-no-properties (line-beginning-position)
 | 
			
		||||
                                  (line-end-position)))
 | 
			
		||||
 | 
			
		||||
;;; Status mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--status-create-index-function ()
 | 
			
		||||
  "Return an alist of all imenu entries in current buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-create-index-function'."
 | 
			
		||||
  (magit-imenu--index-function
 | 
			
		||||
   '(file commit stash)
 | 
			
		||||
   '(unpushed unstaged unpulled untracked staged stashes)))
 | 
			
		||||
 | 
			
		||||
;;;; Refs mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--refs-create-index-function ()
 | 
			
		||||
  "Return an alist of all imenu entries in current buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-create-index-function'."
 | 
			
		||||
  (magit-imenu--index-function
 | 
			
		||||
   '(branch commit tag)
 | 
			
		||||
   '(local remote tags)))
 | 
			
		||||
 | 
			
		||||
;;;; Cherry mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--cherry-create-index-function ()
 | 
			
		||||
  "Return an alist of all imenu entries in current buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-create-index-function'."
 | 
			
		||||
  (magit-imenu--index-function
 | 
			
		||||
   '(commit)
 | 
			
		||||
   '(cherries)))
 | 
			
		||||
 | 
			
		||||
;;;; Submodule list mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--submodule-prev-index-position-function ()
 | 
			
		||||
  "Move point to previous line in magit-submodule-list buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-prev-index-position-function'."
 | 
			
		||||
  (unless (bobp)
 | 
			
		||||
    (forward-line -1)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--submodule-extract-index-name-function ()
 | 
			
		||||
  "Return imenu name for line at point.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-extract-index-name-function'.  Point should be at the
 | 
			
		||||
beginning of the line."
 | 
			
		||||
  (elt (tabulated-list-get-entry) 0))
 | 
			
		||||
 | 
			
		||||
;;;; Repolist mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--repolist-prev-index-position-function ()
 | 
			
		||||
  "Move point to previous line in magit-repolist buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-prev-index-position-function'."
 | 
			
		||||
  (unless (bobp)
 | 
			
		||||
    (forward-line -1)))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--repolist-extract-index-name-function ()
 | 
			
		||||
  "Return imenu name for line at point.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-extract-index-name-function'.  Point should be at the
 | 
			
		||||
beginning of the line."
 | 
			
		||||
  (let ((entry (tabulated-list-get-entry)))
 | 
			
		||||
    (format "%s (%s)"
 | 
			
		||||
            (elt entry 0)
 | 
			
		||||
            (elt entry (1- (length entry))))))
 | 
			
		||||
 | 
			
		||||
;;;; Process mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--process-prev-index-position-function ()
 | 
			
		||||
  "Move point to previous process in magit-process buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-prev-index-position-function'."
 | 
			
		||||
  (magit-section--backward-find
 | 
			
		||||
   (lambda ()
 | 
			
		||||
     (eq (oref (magit-current-section) type) 'process))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--process-extract-index-name-function ()
 | 
			
		||||
  "Return imenu name for line at point.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-extract-index-name-function'.  Point should be at the
 | 
			
		||||
beginning of the line."
 | 
			
		||||
  (buffer-substring-no-properties (line-beginning-position)
 | 
			
		||||
                                  (line-end-position)))
 | 
			
		||||
 | 
			
		||||
;;;; Rebase mode
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--rebase-prev-index-position-function ()
 | 
			
		||||
  "Move point to previous commit in git-rebase buffer.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-prev-index-position-function'."
 | 
			
		||||
  (catch 'found
 | 
			
		||||
    (while (not (bobp))
 | 
			
		||||
      (git-rebase-backward-line)
 | 
			
		||||
      (when (git-rebase-line-p)
 | 
			
		||||
        (throw 'found t)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-imenu--rebase-extract-index-name-function ()
 | 
			
		||||
  "Return imenu name for line at point.
 | 
			
		||||
This function is used as a value for
 | 
			
		||||
`imenu-extract-index-name-function'.  Point should be at the
 | 
			
		||||
beginning of the line."
 | 
			
		||||
  (buffer-substring-no-properties (line-beginning-position)
 | 
			
		||||
                                  (line-end-position)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-imenu)
 | 
			
		||||
;;; magit-imenu.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,241 +0,0 @@
 | 
			
		||||
;;; magit-margin.el --- margins in Magit buffers  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements support for showing additional information
 | 
			
		||||
;; in the margins of Magit buffers.  Currently this is only used for
 | 
			
		||||
;; commits, for which the committer date or age, and optionally the
 | 
			
		||||
;; author name are shown.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'dash)
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit-section)
 | 
			
		||||
(require 'magit-transient)
 | 
			
		||||
(require 'magit-mode)
 | 
			
		||||
 | 
			
		||||
(defgroup magit-margin nil
 | 
			
		||||
  "Information Magit displays in the margin.
 | 
			
		||||
 | 
			
		||||
You can change the STYLE and AUTHOR-WIDTH of all `magit-*-margin'
 | 
			
		||||
options to the same values by customizing `magit-log-margin'
 | 
			
		||||
*before* `magit' is loaded.  If you do that, then the respective
 | 
			
		||||
values for the other options will default to what you have set
 | 
			
		||||
for that variable.  Likewise if you set `magit-log-margin's INIT
 | 
			
		||||
to nil, then that is used in the default of all other options.  But
 | 
			
		||||
setting it to t, i.e. re-enforcing the default for that option,
 | 
			
		||||
does not carry to other options."
 | 
			
		||||
  :link '(info-link "(magit)Log Margin")
 | 
			
		||||
  :group 'magit-log)
 | 
			
		||||
 | 
			
		||||
(defvar-local magit-buffer-margin nil)
 | 
			
		||||
(put 'magit-buffer-margin 'permanent-local t)
 | 
			
		||||
 | 
			
		||||
(defvar-local magit-set-buffer-margin-refresh nil)
 | 
			
		||||
 | 
			
		||||
(defvar magit--age-spec)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
(transient-define-prefix magit-margin-settings ()
 | 
			
		||||
  "Change what information is displayed in the margin."
 | 
			
		||||
  :info-manual "(magit) Log Margin"
 | 
			
		||||
  ["Margin"
 | 
			
		||||
   ("L" "Toggle visibility" magit-toggle-margin)
 | 
			
		||||
   ("l" "Cycle style"       magit-cycle-margin-style)
 | 
			
		||||
   ("d" "Toggle details"    magit-toggle-margin-details)
 | 
			
		||||
   ("v" "Change verbosity"  magit-refs-set-show-commit-count
 | 
			
		||||
    :if-derived magit-refs-mode)])
 | 
			
		||||
 | 
			
		||||
(defun magit-toggle-margin ()
 | 
			
		||||
  "Show or hide the Magit margin."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (unless (magit-margin-option)
 | 
			
		||||
    (user-error "Magit margin isn't supported in this buffer"))
 | 
			
		||||
  (setcar magit-buffer-margin (not (magit-buffer-margin-p)))
 | 
			
		||||
  (magit-set-buffer-margin))
 | 
			
		||||
 | 
			
		||||
(defun magit-cycle-margin-style ()
 | 
			
		||||
  "Cycle style used for the Magit margin."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (unless (magit-margin-option)
 | 
			
		||||
    (user-error "Magit margin isn't supported in this buffer"))
 | 
			
		||||
  ;; This is only suitable for commit margins (there are not others).
 | 
			
		||||
  (setf (cadr magit-buffer-margin)
 | 
			
		||||
        (pcase (cadr magit-buffer-margin)
 | 
			
		||||
          (`age 'age-abbreviated)
 | 
			
		||||
          (`age-abbreviated
 | 
			
		||||
           (let ((default (cadr (symbol-value (magit-margin-option)))))
 | 
			
		||||
             (if (stringp default) default "%Y-%m-%d %H:%M ")))
 | 
			
		||||
          (_ 'age)))
 | 
			
		||||
  (magit-set-buffer-margin nil t))
 | 
			
		||||
 | 
			
		||||
(defun magit-toggle-margin-details ()
 | 
			
		||||
  "Show or hide details in the Magit margin."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (unless (magit-margin-option)
 | 
			
		||||
    (user-error "Magit margin isn't supported in this buffer"))
 | 
			
		||||
  (setf (nth 3 magit-buffer-margin)
 | 
			
		||||
        (not (nth 3 magit-buffer-margin)))
 | 
			
		||||
  (magit-set-buffer-margin nil t))
 | 
			
		||||
 | 
			
		||||
;;; Core
 | 
			
		||||
 | 
			
		||||
(defun magit-buffer-margin-p ()
 | 
			
		||||
  (car magit-buffer-margin))
 | 
			
		||||
 | 
			
		||||
(defun magit-margin-option ()
 | 
			
		||||
  (pcase major-mode
 | 
			
		||||
    (`magit-cherry-mode     'magit-cherry-margin)
 | 
			
		||||
    (`magit-log-mode        'magit-log-margin)
 | 
			
		||||
    (`magit-log-select-mode 'magit-log-select-margin)
 | 
			
		||||
    (`magit-reflog-mode     'magit-reflog-margin)
 | 
			
		||||
    (`magit-refs-mode       'magit-refs-margin)
 | 
			
		||||
    (`magit-stashes-mode    'magit-stashes-margin)
 | 
			
		||||
    (`magit-status-mode     'magit-status-margin)
 | 
			
		||||
    (`forge-notifications-mode 'magit-status-margin)))
 | 
			
		||||
 | 
			
		||||
(defun magit-set-buffer-margin (&optional reset refresh)
 | 
			
		||||
  (when-let ((option (magit-margin-option)))
 | 
			
		||||
    (let* ((default (symbol-value option))
 | 
			
		||||
           (default-width (nth 2 default)))
 | 
			
		||||
      (when (or reset (not magit-buffer-margin))
 | 
			
		||||
        (setq magit-buffer-margin (copy-sequence default)))
 | 
			
		||||
      (pcase-let ((`(,enable ,style ,_width ,details ,details-width)
 | 
			
		||||
                   magit-buffer-margin))
 | 
			
		||||
        (when (functionp default-width)
 | 
			
		||||
          (setf (nth 2 magit-buffer-margin)
 | 
			
		||||
                (funcall default-width style details details-width)))
 | 
			
		||||
        (dolist (window (get-buffer-window-list nil nil 0))
 | 
			
		||||
          (with-selected-window window
 | 
			
		||||
            (magit-set-window-margin window)
 | 
			
		||||
            (if enable
 | 
			
		||||
                (add-hook  'window-configuration-change-hook
 | 
			
		||||
                           'magit-set-window-margin nil t)
 | 
			
		||||
              (remove-hook 'window-configuration-change-hook
 | 
			
		||||
                           'magit-set-window-margin t))))
 | 
			
		||||
        (when (and enable (or refresh magit-set-buffer-margin-refresh))
 | 
			
		||||
          (magit-refresh-buffer))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-set-window-margin (&optional window)
 | 
			
		||||
  (when (or window (setq window (get-buffer-window)))
 | 
			
		||||
    (with-selected-window window
 | 
			
		||||
      (set-window-margins
 | 
			
		||||
       nil (car (window-margins))
 | 
			
		||||
       (and (magit-buffer-margin-p)
 | 
			
		||||
            (nth 2 magit-buffer-margin))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-make-margin-overlay (&optional string previous-line)
 | 
			
		||||
  (if previous-line
 | 
			
		||||
      (save-excursion
 | 
			
		||||
        (forward-line -1)
 | 
			
		||||
        (magit-make-margin-overlay string))
 | 
			
		||||
    ;; Don't put the overlay on the complete line to work around #1880.
 | 
			
		||||
    (let ((o (make-overlay (1+ (line-beginning-position))
 | 
			
		||||
                           (line-end-position)
 | 
			
		||||
                           nil t)))
 | 
			
		||||
      (overlay-put o 'evaporate t)
 | 
			
		||||
      (overlay-put o 'before-string
 | 
			
		||||
                   (propertize "o" 'display
 | 
			
		||||
                               (list (list 'margin 'right-margin)
 | 
			
		||||
                                     (or string " ")))))))
 | 
			
		||||
 | 
			
		||||
(defun magit-maybe-make-margin-overlay ()
 | 
			
		||||
  (when (or (magit-section-match
 | 
			
		||||
             '(unpulled unpushed recent stashes local cherries)
 | 
			
		||||
             magit-insert-section--current)
 | 
			
		||||
            (and (eq major-mode 'magit-refs-mode)
 | 
			
		||||
                 (magit-section-match
 | 
			
		||||
                  '(remote commit tags)
 | 
			
		||||
                  magit-insert-section--current)))
 | 
			
		||||
    (magit-make-margin-overlay nil t)))
 | 
			
		||||
 | 
			
		||||
;;; Custom Support
 | 
			
		||||
 | 
			
		||||
(defun magit-margin-set-variable (mode symbol value)
 | 
			
		||||
  (set-default symbol value)
 | 
			
		||||
  (message "Updating margins in %s buffers..." mode)
 | 
			
		||||
  (dolist (buffer (buffer-list))
 | 
			
		||||
    (with-current-buffer buffer
 | 
			
		||||
      (when (eq major-mode mode)
 | 
			
		||||
        (magit-set-buffer-margin t)
 | 
			
		||||
        (magit-refresh))))
 | 
			
		||||
  (message "Updating margins in %s buffers...done" mode))
 | 
			
		||||
 | 
			
		||||
(defconst magit-log-margin--custom-type
 | 
			
		||||
  '(list (boolean :tag "Show margin initially")
 | 
			
		||||
         (choice  :tag "Show committer"
 | 
			
		||||
                  (string :tag "date using time-format" "%Y-%m-%d %H:%M ")
 | 
			
		||||
                  (const  :tag "date's age" age)
 | 
			
		||||
                  (const  :tag "date's age (abbreviated)" age-abbreviated))
 | 
			
		||||
         (const   :tag "Calculate width using magit-log-margin-width"
 | 
			
		||||
                  magit-log-margin-width)
 | 
			
		||||
         (boolean :tag "Show author name by default")
 | 
			
		||||
         (integer :tag "Show author name using width")))
 | 
			
		||||
 | 
			
		||||
;;; Time Utilities
 | 
			
		||||
 | 
			
		||||
(defvar magit--age-spec
 | 
			
		||||
  `((?Y "year"   "years"   ,(round (* 60 60 24 365.2425)))
 | 
			
		||||
    (?M "month"  "months"  ,(round (* 60 60 24 30.436875)))
 | 
			
		||||
    (?w "week"   "weeks"   ,(* 60 60 24 7))
 | 
			
		||||
    (?d "day"    "days"    ,(* 60 60 24))
 | 
			
		||||
    (?h "hour"   "hours"   ,(* 60 60))
 | 
			
		||||
    (?m "minute" "minutes" 60)
 | 
			
		||||
    (?s "second" "seconds" 1))
 | 
			
		||||
  "Time units used when formatting relative commit ages.
 | 
			
		||||
 | 
			
		||||
The value is a list of time units, beginning with the longest.
 | 
			
		||||
Each element has the form (CHAR UNIT UNITS SECONDS).  UNIT is the
 | 
			
		||||
time unit, UNITS is the plural of that unit.  CHAR is a character
 | 
			
		||||
abbreviation.  And SECONDS is the number of seconds in one UNIT.
 | 
			
		||||
 | 
			
		||||
This is defined as a variable to make it possible to use time
 | 
			
		||||
units for a language other than English.  It is not defined
 | 
			
		||||
as an option, because most other parts of Magit are always in
 | 
			
		||||
English.")
 | 
			
		||||
 | 
			
		||||
(defun magit--age (date &optional abbreviate)
 | 
			
		||||
  (cl-labels ((fn (age spec)
 | 
			
		||||
                  (pcase-let ((`(,char ,unit ,units ,weight) (car spec)))
 | 
			
		||||
                    (let ((cnt (round (/ age weight 1.0))))
 | 
			
		||||
                      (if (or (not (cdr spec))
 | 
			
		||||
                              (>= (/ age weight) 1))
 | 
			
		||||
                          (list cnt (cond (abbreviate char)
 | 
			
		||||
                                          ((= cnt 1) unit)
 | 
			
		||||
                                          (t units)))
 | 
			
		||||
                        (fn age (cdr spec)))))))
 | 
			
		||||
    (fn (abs (- (float-time)
 | 
			
		||||
                (if (stringp date)
 | 
			
		||||
                    (string-to-number date)
 | 
			
		||||
                  date)))
 | 
			
		||||
        magit--age-spec)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-margin)
 | 
			
		||||
;;; magit-margin.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,307 +0,0 @@
 | 
			
		||||
;;; magit-merge.el --- merge functionality  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements merge commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
(require 'magit-diff)
 | 
			
		||||
 | 
			
		||||
(declare-function magit-git-push "magit-push" (branch target args))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-merge "magit" nil t)
 | 
			
		||||
(transient-define-prefix magit-merge ()
 | 
			
		||||
  "Merge branches."
 | 
			
		||||
  :man-page "git-merge"
 | 
			
		||||
  :incompatible '(("--ff-only" "--no-ff"))
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   :if-not magit-merge-in-progress-p
 | 
			
		||||
   ("-f" "Fast-forward only" "--ff-only")
 | 
			
		||||
   ("-n" "No fast-forward"   "--no-ff")
 | 
			
		||||
   (magit-merge:--strategy)
 | 
			
		||||
   (5 magit-diff:--diff-algorithm :argument "--Xdiff-algorithm=")
 | 
			
		||||
   (5 magit:--gpg-sign)]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   :if-not magit-merge-in-progress-p
 | 
			
		||||
   [("m" "Merge"                  magit-merge-plain)
 | 
			
		||||
    ("e" "Merge and edit message" magit-merge-editmsg)
 | 
			
		||||
    ("n" "Merge but don't commit" magit-merge-nocommit)
 | 
			
		||||
    ("a" "Absorb"                 magit-merge-absorb)]
 | 
			
		||||
   [("p" "Preview merge"          magit-merge-preview)
 | 
			
		||||
    ""
 | 
			
		||||
    ("s" "Squash merge"           magit-merge-squash)
 | 
			
		||||
    ("i" "Merge into"             magit-merge-into)]]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   :if magit-merge-in-progress-p
 | 
			
		||||
   ("m" "Commit merge" magit-commit-create)
 | 
			
		||||
   ("a" "Abort merge"  magit-merge-abort)])
 | 
			
		||||
 | 
			
		||||
(defun magit-merge-arguments ()
 | 
			
		||||
  (transient-args 'magit-merge))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-merge:--strategy ()
 | 
			
		||||
  :description "Strategy"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  ;; key for merge and rebase: "-s"
 | 
			
		||||
  ;; key for cherry-pick and revert: "=s"
 | 
			
		||||
  ;; shortarg for merge and rebase: "-s"
 | 
			
		||||
  ;; shortarg for cherry-pick and revert: none
 | 
			
		||||
  :key "-s"
 | 
			
		||||
  :argument "--strategy="
 | 
			
		||||
  :choices '("resolve" "recursive" "octopus" "ours" "subtree"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-plain (rev &optional args nocommit)
 | 
			
		||||
  "Merge commit REV into the current branch; using default message.
 | 
			
		||||
 | 
			
		||||
Unless there are conflicts or a prefix argument is used create a
 | 
			
		||||
merge commit using a generic commit message and without letting
 | 
			
		||||
the user inspect the result.  With a prefix argument pretend the
 | 
			
		||||
merge failed to give the user the opportunity to inspect the
 | 
			
		||||
merge.
 | 
			
		||||
 | 
			
		||||
\(git merge --no-edit|--no-commit [ARGS] REV)"
 | 
			
		||||
  (interactive (list (magit-read-other-branch-or-commit "Merge")
 | 
			
		||||
                     (magit-merge-arguments)
 | 
			
		||||
                     current-prefix-arg))
 | 
			
		||||
  (magit-merge-assert)
 | 
			
		||||
  (magit-run-git-async "merge" (if nocommit "--no-commit" "--no-edit") args rev))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-editmsg (rev &optional args)
 | 
			
		||||
  "Merge commit REV into the current branch; and edit message.
 | 
			
		||||
Perform the merge and prepare a commit message but let the user
 | 
			
		||||
edit it.
 | 
			
		||||
\n(git merge --edit --no-ff [ARGS] REV)"
 | 
			
		||||
  (interactive (list (magit-read-other-branch-or-commit "Merge")
 | 
			
		||||
                     (magit-merge-arguments)))
 | 
			
		||||
  (magit-merge-assert)
 | 
			
		||||
  (cl-pushnew "--no-ff" args :test #'equal)
 | 
			
		||||
  (apply #'magit-run-git-with-editor "merge" "--edit"
 | 
			
		||||
         (append (delete "--ff-only" args)
 | 
			
		||||
                 (list rev))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-nocommit (rev &optional args)
 | 
			
		||||
  "Merge commit REV into the current branch; pretending it failed.
 | 
			
		||||
Pretend the merge failed to give the user the opportunity to
 | 
			
		||||
inspect the merge and change the commit message.
 | 
			
		||||
\n(git merge --no-commit --no-ff [ARGS] REV)"
 | 
			
		||||
  (interactive (list (magit-read-other-branch-or-commit "Merge")
 | 
			
		||||
                     (magit-merge-arguments)))
 | 
			
		||||
  (magit-merge-assert)
 | 
			
		||||
  (cl-pushnew "--no-ff" args :test #'equal)
 | 
			
		||||
  (magit-run-git-async "merge" "--no-commit" args rev))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-into (branch &optional args)
 | 
			
		||||
  "Merge the current branch into BRANCH and remove the former.
 | 
			
		||||
 | 
			
		||||
Before merging, force push the source branch to its push-remote,
 | 
			
		||||
provided the respective remote branch already exists, ensuring
 | 
			
		||||
that the respective pull-request (if any) won't get stuck on some
 | 
			
		||||
obsolete version of the commits that are being merged.  Finally
 | 
			
		||||
if `forge-branch-pullreq' was used to create the merged branch,
 | 
			
		||||
branch, then also remove the respective remote branch."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-other-local-branch
 | 
			
		||||
          (format "Merge `%s' into"
 | 
			
		||||
                  (or (magit-get-current-branch)
 | 
			
		||||
                      (magit-rev-parse "HEAD")))
 | 
			
		||||
          nil
 | 
			
		||||
          (when-let ((upstream (magit-get-upstream-branch))
 | 
			
		||||
                     (upstream (cdr (magit-split-branch-name upstream))))
 | 
			
		||||
            (and (magit-branch-p upstream) upstream)))
 | 
			
		||||
         (magit-merge-arguments)))
 | 
			
		||||
  (let ((current (magit-get-current-branch))
 | 
			
		||||
        (head (magit-rev-parse "HEAD")))
 | 
			
		||||
    (when (zerop (magit-call-git "checkout" branch))
 | 
			
		||||
      (if current
 | 
			
		||||
          (magit--merge-absorb current args)
 | 
			
		||||
        (magit-run-git-with-editor "merge" args head)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-absorb (branch &optional args)
 | 
			
		||||
  "Merge BRANCH into the current branch and remove the former.
 | 
			
		||||
 | 
			
		||||
Before merging, force push the source branch to its push-remote,
 | 
			
		||||
provided the respective remote branch already exists, ensuring
 | 
			
		||||
that the respective pull-request (if any) won't get stuck on some
 | 
			
		||||
obsolete version of the commits that are being merged.  Finally
 | 
			
		||||
if `forge-branch-pullreq' was used to create the merged branch,
 | 
			
		||||
then also remove the respective remote branch."
 | 
			
		||||
  (interactive (list (magit-read-other-local-branch "Absorb branch")
 | 
			
		||||
                     (magit-merge-arguments)))
 | 
			
		||||
  (magit--merge-absorb branch args))
 | 
			
		||||
 | 
			
		||||
(defun magit--merge-absorb (branch args)
 | 
			
		||||
  (when (equal branch "master")
 | 
			
		||||
    (unless (yes-or-no-p
 | 
			
		||||
             "Do you really want to merge `master' into another branch? ")
 | 
			
		||||
      (user-error "Abort")))
 | 
			
		||||
  (if-let ((target (magit-get-push-branch branch t)))
 | 
			
		||||
      (progn
 | 
			
		||||
        (magit-git-push branch target (list "--force-with-lease"))
 | 
			
		||||
        (set-process-sentinel
 | 
			
		||||
         magit-this-process
 | 
			
		||||
         (lambda (process event)
 | 
			
		||||
           (when (memq (process-status process) '(exit signal))
 | 
			
		||||
             (if (not (zerop (process-exit-status process)))
 | 
			
		||||
                 (magit-process-sentinel process event)
 | 
			
		||||
               (process-put process 'inhibit-refresh t)
 | 
			
		||||
               (magit-process-sentinel process event)
 | 
			
		||||
               (magit--merge-absorb-1 branch args))))))
 | 
			
		||||
    (magit--merge-absorb-1 branch args)))
 | 
			
		||||
 | 
			
		||||
(defun magit--merge-absorb-1 (branch args)
 | 
			
		||||
  (if-let ((pr (magit-get "branch" branch "pullRequest")))
 | 
			
		||||
      (magit-run-git-async
 | 
			
		||||
       "merge" args "-m"
 | 
			
		||||
       (format "Merge branch '%s'%s [#%s]"
 | 
			
		||||
               branch
 | 
			
		||||
               (let ((current (magit-get-current-branch)))
 | 
			
		||||
                 (if (equal current "master") "" (format " into %s" current)))
 | 
			
		||||
               pr)
 | 
			
		||||
       branch)
 | 
			
		||||
    (magit-run-git-async "merge" args "--no-edit" branch))
 | 
			
		||||
  (set-process-sentinel
 | 
			
		||||
   magit-this-process
 | 
			
		||||
   (lambda (process event)
 | 
			
		||||
     (when (memq (process-status process) '(exit signal))
 | 
			
		||||
       (if (> (process-exit-status process) 0)
 | 
			
		||||
           (magit-process-sentinel process event)
 | 
			
		||||
         (process-put process 'inhibit-refresh t)
 | 
			
		||||
         (magit-process-sentinel process event)
 | 
			
		||||
         (magit-branch-maybe-delete-pr-remote branch)
 | 
			
		||||
         (magit-branch-unset-pushRemote branch)
 | 
			
		||||
         (magit-run-git "branch" "-D" branch))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-squash (rev)
 | 
			
		||||
  "Squash commit REV into the current branch; don't create a commit.
 | 
			
		||||
\n(git merge --squash REV)"
 | 
			
		||||
  (interactive (list (magit-read-other-branch-or-commit "Squash")))
 | 
			
		||||
  (magit-merge-assert)
 | 
			
		||||
  (magit-run-git-async "merge" "--squash" rev))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-preview (rev)
 | 
			
		||||
  "Preview result of merging REV into the current branch."
 | 
			
		||||
  (interactive (list (magit-read-other-branch-or-commit "Preview merge")))
 | 
			
		||||
  (magit-merge-preview-setup-buffer rev))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-merge-abort ()
 | 
			
		||||
  "Abort the current merge operation.
 | 
			
		||||
\n(git merge --abort)"
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (unless (file-exists-p (magit-git-dir "MERGE_HEAD"))
 | 
			
		||||
    (user-error "No merge in progress"))
 | 
			
		||||
  (magit-confirm 'abort-merge)
 | 
			
		||||
  (magit-run-git-async "merge" "--abort"))
 | 
			
		||||
 | 
			
		||||
(defun magit-checkout-stage (file arg)
 | 
			
		||||
  "During a conflict checkout and stage side, or restore conflict."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((file (magit-completing-read "Checkout file"
 | 
			
		||||
                                      (magit-tracked-files) nil nil nil
 | 
			
		||||
                                      'magit-read-file-hist
 | 
			
		||||
                                      (magit-current-file))))
 | 
			
		||||
     (cond ((member file (magit-unmerged-files))
 | 
			
		||||
            (list file (magit-checkout-read-stage file)))
 | 
			
		||||
           ((yes-or-no-p (format "Restore conflicts in %s? " file))
 | 
			
		||||
            (list file "--merge"))
 | 
			
		||||
           (t
 | 
			
		||||
            (user-error "Quit")))))
 | 
			
		||||
  (pcase (cons arg (cddr (car (magit-file-status file))))
 | 
			
		||||
    ((or `("--ours"   ?D ,_)
 | 
			
		||||
         `("--theirs" ,_ ?D))
 | 
			
		||||
     (magit-run-git "rm" "--" file))
 | 
			
		||||
    (_ (if (equal arg "--merge")
 | 
			
		||||
           ;; This fails if the file was deleted on one
 | 
			
		||||
           ;; side.  And we cannot do anything about it.
 | 
			
		||||
           (magit-run-git "checkout" "--merge" "--" file)
 | 
			
		||||
         (magit-call-git "checkout" arg "--" file)
 | 
			
		||||
         (magit-run-git "add" "-u" "--" file)))))
 | 
			
		||||
 | 
			
		||||
;;; Utilities
 | 
			
		||||
 | 
			
		||||
(defun magit-merge-in-progress-p ()
 | 
			
		||||
  (file-exists-p (magit-git-dir "MERGE_HEAD")))
 | 
			
		||||
 | 
			
		||||
(defun magit--merge-range (&optional head)
 | 
			
		||||
  (unless head
 | 
			
		||||
    (setq head (magit-get-shortname
 | 
			
		||||
                (car (magit-file-lines (magit-git-dir "MERGE_HEAD"))))))
 | 
			
		||||
  (and head
 | 
			
		||||
       (concat (magit-git-string "merge-base" "--octopus" "HEAD" head)
 | 
			
		||||
               ".." head)))
 | 
			
		||||
 | 
			
		||||
(defun magit-merge-assert ()
 | 
			
		||||
  (or (not (magit-anything-modified-p t))
 | 
			
		||||
      (magit-confirm 'merge-dirty
 | 
			
		||||
        "Merging with dirty worktree is risky.  Continue")))
 | 
			
		||||
 | 
			
		||||
(defun magit-checkout-read-stage (file)
 | 
			
		||||
  (magit-read-char-case (format "For %s checkout: " file) t
 | 
			
		||||
    (?o "[o]ur stage"   "--ours")
 | 
			
		||||
    (?t "[t]heir stage" "--theirs")
 | 
			
		||||
    (?c "[c]onflict"    "--merge")))
 | 
			
		||||
 | 
			
		||||
;;; Sections
 | 
			
		||||
 | 
			
		||||
(defvar magit-unmerged-section-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (define-key map [remap magit-visit-thing] 'magit-diff-dwim)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for `unmerged' sections.")
 | 
			
		||||
 | 
			
		||||
(defun magit-insert-merge-log ()
 | 
			
		||||
  "Insert section for the on-going merge.
 | 
			
		||||
Display the heads that are being merged.
 | 
			
		||||
If no merge is in progress, do nothing."
 | 
			
		||||
  (when (magit-merge-in-progress-p)
 | 
			
		||||
    (let* ((heads (mapcar #'magit-get-shortname
 | 
			
		||||
                          (magit-file-lines (magit-git-dir "MERGE_HEAD"))))
 | 
			
		||||
           (range (magit--merge-range (car heads))))
 | 
			
		||||
      (magit-insert-section (unmerged range)
 | 
			
		||||
        (magit-insert-heading
 | 
			
		||||
          (format "Merging %s:" (mapconcat #'identity heads ", ")))
 | 
			
		||||
        (magit-insert-log
 | 
			
		||||
         range
 | 
			
		||||
         (let ((args magit-buffer-log-args))
 | 
			
		||||
           (unless (member "--decorate=full" magit-buffer-log-args)
 | 
			
		||||
             (push "--decorate=full" args))
 | 
			
		||||
           args))))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-merge)
 | 
			
		||||
;;; magit-merge.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,200 +0,0 @@
 | 
			
		||||
;;; magit-notes.el --- notes support  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements support for `git-notes'.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-notes "magit" nil t)
 | 
			
		||||
(transient-define-prefix magit-notes ()
 | 
			
		||||
  "Edit notes attached to commits."
 | 
			
		||||
  :man-page "git-notes"
 | 
			
		||||
  ["Configure local settings"
 | 
			
		||||
   ("c" magit-core.notesRef)
 | 
			
		||||
   ("d" magit-notes.displayRef)]
 | 
			
		||||
  ["Configure global settings"
 | 
			
		||||
   ("C" magit-global-core.notesRef)
 | 
			
		||||
   ("D" magit-global-notes.displayRef)]
 | 
			
		||||
  ["Arguments for prune"
 | 
			
		||||
   :if-not magit-notes-merging-p
 | 
			
		||||
   ("-n" "Dry run" ("-n" "--dry-run"))]
 | 
			
		||||
  ["Arguments for edit and remove"
 | 
			
		||||
   :if-not magit-notes-merging-p
 | 
			
		||||
   (magit-notes:--ref)]
 | 
			
		||||
  ["Arguments for merge"
 | 
			
		||||
   :if-not magit-notes-merging-p
 | 
			
		||||
   (magit-notes:--strategy)]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   :if-not magit-notes-merging-p
 | 
			
		||||
   ("T" "Edit"         magit-notes-edit)
 | 
			
		||||
   ("r" "Remove"       magit-notes-remove)
 | 
			
		||||
   ("m" "Merge"        magit-notes-merge)
 | 
			
		||||
   ("p" "Prune"        magit-notes-prune)]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   :if magit-notes-merging-p
 | 
			
		||||
   ("c" "Commit merge" magit-notes-merge-commit)
 | 
			
		||||
   ("a" "Abort merge"  magit-notes-merge-abort)])
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-merging-p ()
 | 
			
		||||
  (let ((dir (magit-git-dir "NOTES_MERGE_WORKTREE")))
 | 
			
		||||
    (and (file-directory-p dir)
 | 
			
		||||
         (directory-files dir nil "^[^.]"))))
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-core.notesRef ()
 | 
			
		||||
  :class 'magit--git-variable
 | 
			
		||||
  :variable "core.notesRef"
 | 
			
		||||
  :reader 'magit-notes-read-ref
 | 
			
		||||
  :prompt "Set local core.notesRef")
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-notes.displayRef ()
 | 
			
		||||
  :class 'magit--git-variable
 | 
			
		||||
  :variable "notes.displayRef"
 | 
			
		||||
  :multi-value t
 | 
			
		||||
  :reader 'magit-notes-read-refs
 | 
			
		||||
  :prompt "Set local notes.displayRef")
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-global-core.notesRef ()
 | 
			
		||||
  :class 'magit--git-variable
 | 
			
		||||
  :variable "core.notesRef"
 | 
			
		||||
  :reader 'magit-notes-read-ref
 | 
			
		||||
  :prompt "Set global core.notesRef")
 | 
			
		||||
 | 
			
		||||
(transient-define-infix magit-global-notes.displayRef ()
 | 
			
		||||
  :class 'magit--git-variable
 | 
			
		||||
  :variable "notes.displayRef"
 | 
			
		||||
  :multi-value t
 | 
			
		||||
  :reader 'magit-notes-read-refs
 | 
			
		||||
  :prompt "Set global notes.displayRef")
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-notes:--ref ()
 | 
			
		||||
  :description "Merge strategy"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "-r"
 | 
			
		||||
  :argument "--ref="
 | 
			
		||||
  :reader 'magit-notes-read-ref)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-notes:--strategy ()
 | 
			
		||||
  :description "Merge strategy"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :shortarg "-s"
 | 
			
		||||
  :argument "--strategy="
 | 
			
		||||
  :choices '("manual" "ours" "theirs" "union" "cat_sort_uniq"))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-edit (commit &optional ref)
 | 
			
		||||
  "Edit the note attached to COMMIT.
 | 
			
		||||
REF is the notes ref used to store the notes.
 | 
			
		||||
 | 
			
		||||
Interactively or when optional REF is nil use the value of Git
 | 
			
		||||
variable `core.notesRef' or \"refs/notes/commits\" if that is
 | 
			
		||||
undefined."
 | 
			
		||||
  (interactive (magit-notes-read-args "Edit notes"))
 | 
			
		||||
  (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref))
 | 
			
		||||
                             "edit" commit))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-remove (commit &optional ref)
 | 
			
		||||
  "Remove the note attached to COMMIT.
 | 
			
		||||
REF is the notes ref from which the note is removed.
 | 
			
		||||
 | 
			
		||||
Interactively or when optional REF is nil use the value of Git
 | 
			
		||||
variable `core.notesRef' or \"refs/notes/commits\" if that is
 | 
			
		||||
undefined."
 | 
			
		||||
  (interactive (magit-notes-read-args "Remove notes"))
 | 
			
		||||
  (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref))
 | 
			
		||||
                             "remove" commit))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-merge (ref)
 | 
			
		||||
  "Merge the notes ref REF into the current notes ref.
 | 
			
		||||
 | 
			
		||||
The current notes ref is the value of Git variable
 | 
			
		||||
`core.notesRef' or \"refs/notes/commits\" if that is undefined.
 | 
			
		||||
 | 
			
		||||
When there are conflicts, then they have to be resolved in the
 | 
			
		||||
temporary worktree \".git/NOTES_MERGE_WORKTREE\".  When
 | 
			
		||||
done use `magit-notes-merge-commit' to finish.  To abort
 | 
			
		||||
use `magit-notes-merge-abort'."
 | 
			
		||||
  (interactive (list (magit-read-string-ns "Merge reference")))
 | 
			
		||||
  (magit-run-git-with-editor "notes" "merge" ref))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-merge-commit ()
 | 
			
		||||
  "Commit the current notes ref merge.
 | 
			
		||||
Also see `magit-notes-merge'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-run-git-with-editor "notes" "merge" "--commit"))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-merge-abort ()
 | 
			
		||||
  "Abort the current notes ref merge.
 | 
			
		||||
Also see `magit-notes-merge'."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-run-git-with-editor "notes" "merge" "--abort"))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-prune (&optional dry-run)
 | 
			
		||||
  "Remove notes about unreachable commits."
 | 
			
		||||
  (interactive (list (and (member "--dry-run" (transient-args 'magit-notes)) t)))
 | 
			
		||||
  (when dry-run
 | 
			
		||||
    (magit-process-buffer))
 | 
			
		||||
  (magit-run-git-with-editor "notes" "prune" (and dry-run "--dry-run")))
 | 
			
		||||
 | 
			
		||||
;;; Readers
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-read-ref (prompt _initial-input history)
 | 
			
		||||
  (--when-let (magit-completing-read
 | 
			
		||||
               prompt (magit-list-notes-refnames) nil nil
 | 
			
		||||
               (--when-let (magit-get "core.notesRef")
 | 
			
		||||
                 (if (string-prefix-p "refs/notes/" it)
 | 
			
		||||
                     (substring it 11)
 | 
			
		||||
                   it))
 | 
			
		||||
               history)
 | 
			
		||||
    (if (string-prefix-p "refs/" it)
 | 
			
		||||
        it
 | 
			
		||||
      (concat "refs/notes/" it))))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-read-refs (prompt)
 | 
			
		||||
  (mapcar (lambda (ref)
 | 
			
		||||
            (if (string-prefix-p "refs/" ref)
 | 
			
		||||
                ref
 | 
			
		||||
              (concat "refs/notes/" ref)))
 | 
			
		||||
          (completing-read-multiple
 | 
			
		||||
           (concat prompt ": ")
 | 
			
		||||
           (magit-list-notes-refnames) nil nil
 | 
			
		||||
           (mapconcat (lambda (ref)
 | 
			
		||||
                        (if (string-prefix-p "refs/notes/" ref)
 | 
			
		||||
                            (substring ref 11)
 | 
			
		||||
                          ref))
 | 
			
		||||
                      (magit-get-all "notes.displayRef")
 | 
			
		||||
                      ","))))
 | 
			
		||||
 | 
			
		||||
(defun magit-notes-read-args (prompt)
 | 
			
		||||
 (list (magit-read-branch-or-commit prompt (magit-stash-at-point))
 | 
			
		||||
       (--when-let (--first (string-match "^--ref=\\(.+\\)" it)
 | 
			
		||||
                            (transient-args 'magit-notes))
 | 
			
		||||
         (match-string 1 it))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-notes)
 | 
			
		||||
;;; magit-notes.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,109 +0,0 @@
 | 
			
		||||
;;; magit-obsolete.el --- obsolete definitions  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library defines aliases for obsolete variables and functions.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Obsolete since v3.0.0
 | 
			
		||||
 | 
			
		||||
(define-obsolete-function-alias 'magit-diff-visit-file-worktree
 | 
			
		||||
  'magit-diff-visit-worktree-file "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(define-obsolete-function-alias 'magit-status-internal
 | 
			
		||||
  'magit-status-setup-buffer "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(define-obsolete-variable-alias 'magit-mode-setup-hook
 | 
			
		||||
  'magit-setup-buffer-hook "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(define-obsolete-variable-alias 'magit-branch-popup-show-variables
 | 
			
		||||
  'magit-branch-direct-configure "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(define-obsolete-function-alias 'magit-dispatch-popup
 | 
			
		||||
  'magit-dispatch "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(define-obsolete-function-alias 'magit-repolist-column-dirty
 | 
			
		||||
  'magit-repolist-column-flag "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(define-obsolete-variable-alias 'magit-disable-line-numbers
 | 
			
		||||
  'magit-section-disable-line-numbers "Magit 3.0.0")
 | 
			
		||||
 | 
			
		||||
(defun magit--magit-popup-warning ()
 | 
			
		||||
  (display-warning 'magit "\
 | 
			
		||||
Magit no longer uses Magit-Popup.
 | 
			
		||||
It now uses Transient.
 | 
			
		||||
See https://emacsair.me/2019/02/14/transient-0.1.
 | 
			
		||||
 | 
			
		||||
However your configuration and/or some third-party package that
 | 
			
		||||
you use still depends on the `magit-popup' package.  But because
 | 
			
		||||
`magit' no longer depends on that, `package' has removed it from
 | 
			
		||||
your system.
 | 
			
		||||
 | 
			
		||||
If some package that you use still depends on `magit-popup' but
 | 
			
		||||
does not declare it as a dependency, then please contact its
 | 
			
		||||
maintainer about that and install `magit-popup' explicitly.
 | 
			
		||||
 | 
			
		||||
If you yourself use functions that are defined in `magit-popup'
 | 
			
		||||
in your configuration, then the next step depends on what you use
 | 
			
		||||
that for.
 | 
			
		||||
 | 
			
		||||
* If you use `magit-popup' to define your own popups but do not
 | 
			
		||||
  modify any of Magit's old popups, then you have to install
 | 
			
		||||
  `magit-popup' explicitly.  (You can also migrate to Transient,
 | 
			
		||||
  but there is no need to rush that.)
 | 
			
		||||
 | 
			
		||||
* If you add additional arguments and/or actions to Magit's popups,
 | 
			
		||||
  then you have to port that to modify the new \"transients\" instead.
 | 
			
		||||
  See https://github.com/magit/magit/wiki/\
 | 
			
		||||
Converting-popup-modifications-to-transient-modifications
 | 
			
		||||
 | 
			
		||||
To find installed packages that still use `magit-popup' you can
 | 
			
		||||
use e.g. \"M-x rgrep RET magit-popup RET RET ~/.emacs.d/ RET\"."))
 | 
			
		||||
(cl-eval-when (eval load)
 | 
			
		||||
  (unless (require (quote magit-popup) nil t)
 | 
			
		||||
    (defun magit-define-popup-switch (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-define-popup-option (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-define-popup-variable (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-define-popup-action (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-define-popup-sequence-action (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-define-popup-key (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-define-popup-keys-deferred (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-change-popup-key (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))
 | 
			
		||||
    (defun magit-remove-popup-key (&rest _)
 | 
			
		||||
      (magit--magit-popup-warning))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-obsolete)
 | 
			
		||||
;;; magit-obsolete.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,331 +0,0 @@
 | 
			
		||||
;;; magit-patch.el --- creating and applying patches  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements patch commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-patch-save-arguments '(exclude "--stat")
 | 
			
		||||
  "Control arguments used by the command `magit-patch-save'.
 | 
			
		||||
 | 
			
		||||
`magit-patch-save' (which see) saves a diff for the changes
 | 
			
		||||
shown in the current buffer in a patch file.  It may use the
 | 
			
		||||
same arguments as used in the buffer or a subset thereof, or
 | 
			
		||||
a constant list of arguments, depending on this option and
 | 
			
		||||
the prefix argument."
 | 
			
		||||
  :package-version '(magit . "2.12.0")
 | 
			
		||||
  :group 'magit-diff
 | 
			
		||||
  :type '(choice (const :tag "use buffer arguments" buffer)
 | 
			
		||||
                 (cons :tag "use buffer arguments except"
 | 
			
		||||
                       (const :format "" exclude)
 | 
			
		||||
                       (repeat :format "%v%i\n"
 | 
			
		||||
                               (string :tag "Argument")))
 | 
			
		||||
                 (repeat :tag "use constant arguments"
 | 
			
		||||
                         (string :tag "Argument"))))
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-patch "magit-patch" nil t)
 | 
			
		||||
(transient-define-prefix magit-patch ()
 | 
			
		||||
  "Create or apply patches."
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   ("c"  "Create patches"     magit-patch-create)
 | 
			
		||||
   ("a"  "Apply patch"        magit-patch-apply)
 | 
			
		||||
   ("s"  "Save diff as patch" magit-patch-save)
 | 
			
		||||
   ("r"  "Request pull"       magit-request-pull)])
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-patch-create "magit-patch" nil t)
 | 
			
		||||
(transient-define-prefix magit-patch-create (range args files)
 | 
			
		||||
  "Create patches for the commits in RANGE.
 | 
			
		||||
When a single commit is given for RANGE, create a patch for the
 | 
			
		||||
changes introduced by that commit (unlike 'git format-patch'
 | 
			
		||||
which creates patches for all commits that are reachable from
 | 
			
		||||
`HEAD' but not from the specified commit)."
 | 
			
		||||
  :man-page "git-format-patch"
 | 
			
		||||
  :incompatible '(("--subject-prefix=" "--rfc"))
 | 
			
		||||
  ["Mail arguments"
 | 
			
		||||
   (6 magit-format-patch:--in-reply-to)
 | 
			
		||||
   (6 magit-format-patch:--thread)
 | 
			
		||||
   (6 magit-format-patch:--from)
 | 
			
		||||
   (6 magit-format-patch:--to)
 | 
			
		||||
   (6 magit-format-patch:--cc)]
 | 
			
		||||
  ["Patch arguments"
 | 
			
		||||
   (magit-format-patch:--base)
 | 
			
		||||
   (magit-format-patch:--reroll-count)
 | 
			
		||||
   (5 magit-format-patch:--interdiff)
 | 
			
		||||
   (magit-format-patch:--range-diff)
 | 
			
		||||
   (magit-format-patch:--subject-prefix)
 | 
			
		||||
   ("C-m r  " "RFC subject prefix" "--rfc")
 | 
			
		||||
   ("C-m l  " "Add cover letter" "--cover-letter")
 | 
			
		||||
   (5 magit-format-patch:--cover-from-description)
 | 
			
		||||
   (5 magit-format-patch:--notes)
 | 
			
		||||
   (magit-format-patch:--output-directory)]
 | 
			
		||||
  ["Diff arguments"
 | 
			
		||||
   (magit-diff:-U)
 | 
			
		||||
   (magit-diff:-M)
 | 
			
		||||
   (magit-diff:-C)
 | 
			
		||||
   (magit-diff:--diff-algorithm)
 | 
			
		||||
   (magit:--)
 | 
			
		||||
   (7 "-b" "Ignore whitespace changes" ("-b" "--ignore-space-change"))
 | 
			
		||||
   (7 "-w" "Ignore all whitespace"     ("-w" "--ignore-all-space"))]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   ("c" "Create patches" magit-patch-create)]
 | 
			
		||||
  (interactive
 | 
			
		||||
   (if (not (eq transient-current-command 'magit-patch-create))
 | 
			
		||||
       (list nil nil nil)
 | 
			
		||||
     (cons (if-let ((revs (magit-region-values 'commit t)))
 | 
			
		||||
               (concat (car (last revs)) "^.." (car revs))
 | 
			
		||||
             (let ((range (magit-read-range-or-commit
 | 
			
		||||
                           "Format range or commit")))
 | 
			
		||||
               (if (string-match-p "\\.\\." range)
 | 
			
		||||
                   range
 | 
			
		||||
                 (format "%s~..%s" range range))))
 | 
			
		||||
           (let ((args (transient-args 'magit-patch-create)))
 | 
			
		||||
             (list (-filter #'stringp args)
 | 
			
		||||
                   (cdr (assoc "--" args)))))))
 | 
			
		||||
  (if (not range)
 | 
			
		||||
      (transient-setup 'magit-patch-create)
 | 
			
		||||
    (magit-run-git "format-patch" range args "--" files)
 | 
			
		||||
    (when (member "--cover-letter" args)
 | 
			
		||||
      (save-match-data
 | 
			
		||||
        (find-file
 | 
			
		||||
         (expand-file-name
 | 
			
		||||
          (concat (--some (and (string-match "\\`--reroll-count=\\(.+\\)" it)
 | 
			
		||||
                               (format "v%s-" (match-string 1 it)))
 | 
			
		||||
                          args)
 | 
			
		||||
                  "0000-cover-letter.patch")
 | 
			
		||||
          (let ((topdir (magit-toplevel)))
 | 
			
		||||
            (or (--some (and (string-match "\\`--output-directory=\\(.+\\)" it)
 | 
			
		||||
                             (expand-file-name (match-string 1 it) topdir))
 | 
			
		||||
                        args)
 | 
			
		||||
                topdir))))))))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--in-reply-to ()
 | 
			
		||||
  :description "In reply to"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m C-r"
 | 
			
		||||
  :argument "--in-reply-to=")
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--thread ()
 | 
			
		||||
  :description "Thread style"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m s  "
 | 
			
		||||
  :argument "--thread="
 | 
			
		||||
  :reader #'magit-format-patch-select-thread-style)
 | 
			
		||||
 | 
			
		||||
(defun magit-format-patch-select-thread-style (&rest _ignore)
 | 
			
		||||
  (magit-read-char-case "Thread style " t
 | 
			
		||||
    (?d "[d]eep" "deep")
 | 
			
		||||
    (?s "[s]hallow" "shallow")))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--base ()
 | 
			
		||||
  :description "Insert base commit"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m b  "
 | 
			
		||||
  :argument "--base="
 | 
			
		||||
  :reader #'magit-format-patch-select-base)
 | 
			
		||||
 | 
			
		||||
(defun magit-format-patch-select-base (prompt initial-input history)
 | 
			
		||||
  (or (magit-completing-read prompt (cons "auto" (magit-list-refnames))
 | 
			
		||||
                             nil nil initial-input history "auto")
 | 
			
		||||
      (user-error "Nothing selected")))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--reroll-count ()
 | 
			
		||||
  :description "Reroll count"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m v  "
 | 
			
		||||
  :shortarg "-v"
 | 
			
		||||
  :argument "--reroll-count="
 | 
			
		||||
  :reader 'transient-read-number-N+)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--interdiff ()
 | 
			
		||||
  :description "Insert interdiff"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m d i"
 | 
			
		||||
  :argument "--interdiff="
 | 
			
		||||
  :reader #'magit-transient-read-revision)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--range-diff ()
 | 
			
		||||
  :description "Insert range-diff"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m d r"
 | 
			
		||||
  :argument "--range-diff="
 | 
			
		||||
  :reader #'magit-format-patch-select-range-diff)
 | 
			
		||||
 | 
			
		||||
(defun magit-format-patch-select-range-diff (prompt _initial-input _history)
 | 
			
		||||
  (magit-read-range-or-commit prompt))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--subject-prefix ()
 | 
			
		||||
  :description "Subject Prefix"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m p  "
 | 
			
		||||
  :argument "--subject-prefix=")
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--cover-from-description ()
 | 
			
		||||
  :description "Use branch description"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m D  "
 | 
			
		||||
  :argument "--cover-from-description="
 | 
			
		||||
  :reader #'magit-format-patch-select-description-mode)
 | 
			
		||||
 | 
			
		||||
(defun magit-format-patch-select-description-mode (&rest _ignore)
 | 
			
		||||
  (magit-read-char-case "Use description as " t
 | 
			
		||||
    (?m "[m]essage" "message")
 | 
			
		||||
    (?s "[s]ubject" "subject")
 | 
			
		||||
    (?a "[a]uto"    "auto")
 | 
			
		||||
    (?n "[n]othing" "none")))
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--notes ()
 | 
			
		||||
  :description "Insert commentary from notes"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m n  "
 | 
			
		||||
  :argument "--notes="
 | 
			
		||||
  :reader #'magit-notes-read-ref)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--from ()
 | 
			
		||||
  :description "From"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m C-f"
 | 
			
		||||
  :argument "--from="
 | 
			
		||||
  :reader 'magit-transient-read-person)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--to ()
 | 
			
		||||
  :description "To"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m C-t"
 | 
			
		||||
  :argument "--to="
 | 
			
		||||
  :reader 'magit-transient-read-person)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--cc ()
 | 
			
		||||
  :description "CC"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m C-c"
 | 
			
		||||
  :argument "--cc="
 | 
			
		||||
  :reader 'magit-transient-read-person)
 | 
			
		||||
 | 
			
		||||
(transient-define-argument magit-format-patch:--output-directory ()
 | 
			
		||||
  :description "Output directory"
 | 
			
		||||
  :class 'transient-option
 | 
			
		||||
  :key "C-m o  "
 | 
			
		||||
  :shortarg "-o"
 | 
			
		||||
  :argument "--output-directory="
 | 
			
		||||
  :reader 'transient-read-existing-directory)
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-patch-apply "magit-patch" nil t)
 | 
			
		||||
(transient-define-prefix magit-patch-apply (file &rest args)
 | 
			
		||||
  "Apply the patch file FILE."
 | 
			
		||||
  :man-page "git-apply"
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   ("-i" "Also apply to index" "--index")
 | 
			
		||||
   ("-c" "Only apply to index" "--cached")
 | 
			
		||||
   ("-3" "Fall back on 3way merge" ("-3" "--3way"))]
 | 
			
		||||
  ["Actions"
 | 
			
		||||
   ("a"  "Apply patch" magit-patch-apply)]
 | 
			
		||||
  (interactive
 | 
			
		||||
   (if (not (eq transient-current-command 'magit-patch-apply))
 | 
			
		||||
       (list nil)
 | 
			
		||||
     (list (expand-file-name
 | 
			
		||||
            (read-file-name "Apply patch: "
 | 
			
		||||
                            default-directory nil nil
 | 
			
		||||
                            (when-let ((file (magit-file-at-point)))
 | 
			
		||||
                              (file-relative-name file))))
 | 
			
		||||
           (transient-args 'magit-patch-apply))))
 | 
			
		||||
  (if (not file)
 | 
			
		||||
      (transient-setup 'magit-patch-apply)
 | 
			
		||||
    (magit-run-git "apply" args "--" (magit-convert-filename-for-git file))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-patch-save (file &optional arg)
 | 
			
		||||
  "Write current diff into patch FILE.
 | 
			
		||||
 | 
			
		||||
What arguments are used to create the patch depends on the value
 | 
			
		||||
of `magit-patch-save-arguments' and whether a prefix argument is
 | 
			
		||||
used.
 | 
			
		||||
 | 
			
		||||
If the value is the symbol `buffer', then use the same arguments
 | 
			
		||||
as the buffer.  With a prefix argument use no arguments.
 | 
			
		||||
 | 
			
		||||
If the value is a list beginning with the symbol `exclude', then
 | 
			
		||||
use the same arguments as the buffer except for those matched by
 | 
			
		||||
entries in the cdr of the list.  The comparison is done using
 | 
			
		||||
`string-prefix-p'.  With a prefix argument use the same arguments
 | 
			
		||||
as the buffer.
 | 
			
		||||
 | 
			
		||||
If the value is a list of strings (including the empty list),
 | 
			
		||||
then use those arguments.  With a prefix argument use the same
 | 
			
		||||
arguments as the buffer.
 | 
			
		||||
 | 
			
		||||
Of course the arguments that are required to actually show the
 | 
			
		||||
same differences as those shown in the buffer are always used."
 | 
			
		||||
  (interactive (list (read-file-name "Write patch file: " default-directory)
 | 
			
		||||
                     current-prefix-arg))
 | 
			
		||||
  (unless (derived-mode-p 'magit-diff-mode)
 | 
			
		||||
    (user-error "Only diff buffers can be saved as patches"))
 | 
			
		||||
  (let ((rev     magit-buffer-range)
 | 
			
		||||
        (typearg magit-buffer-typearg)
 | 
			
		||||
        (args    magit-buffer-diff-args)
 | 
			
		||||
        (files   magit-buffer-diff-files))
 | 
			
		||||
    (cond ((eq magit-patch-save-arguments 'buffer)
 | 
			
		||||
           (when arg
 | 
			
		||||
             (setq args nil)))
 | 
			
		||||
          ((eq (car-safe magit-patch-save-arguments) 'exclude)
 | 
			
		||||
           (unless arg
 | 
			
		||||
             (setq args (-difference args (cdr magit-patch-save-arguments)))))
 | 
			
		||||
          ((not arg)
 | 
			
		||||
           (setq args magit-patch-save-arguments)))
 | 
			
		||||
    (with-temp-file file
 | 
			
		||||
      (magit-git-insert "diff" rev "-p" typearg args "--" files)))
 | 
			
		||||
  (magit-refresh))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-request-pull (url start end)
 | 
			
		||||
  "Request upstream to pull from your public repository.
 | 
			
		||||
 | 
			
		||||
URL is the url of your publicly accessible repository.
 | 
			
		||||
START is a commit that already is in the upstream repository.
 | 
			
		||||
END is the last commit, usually a branch name, which upstream
 | 
			
		||||
is asked to pull.  START has to be reachable from that commit."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-get "remote" (magit-read-remote "Remote") "url")
 | 
			
		||||
         (magit-read-branch-or-commit "Start" (magit-get-upstream-branch))
 | 
			
		||||
         (magit-read-branch-or-commit "End")))
 | 
			
		||||
  (let ((dir default-directory))
 | 
			
		||||
    ;; mu4e changes default-directory
 | 
			
		||||
    (compose-mail)
 | 
			
		||||
    (setq default-directory dir))
 | 
			
		||||
  (message-goto-body)
 | 
			
		||||
  (magit-git-insert "request-pull" start url end)
 | 
			
		||||
  (set-buffer-modified-p nil))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-patch)
 | 
			
		||||
;;; magit-patch.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,12 +0,0 @@
 | 
			
		||||
(define-package "magit" "20200829.921" "A Git porcelain inside Emacs."
 | 
			
		||||
  '((emacs "25.1")
 | 
			
		||||
    (async "20200113")
 | 
			
		||||
    (dash "20200524")
 | 
			
		||||
    (git-commit "20200516")
 | 
			
		||||
    (transient "20200601")
 | 
			
		||||
    (with-editor "20200522"))
 | 
			
		||||
  :commit "f5ea9b2fe50642e305f43958027672cc1abedd8b" :keywords
 | 
			
		||||
  '("git" "tools" "vc"))
 | 
			
		||||
;; Local Variables:
 | 
			
		||||
;; no-byte-compile: t
 | 
			
		||||
;; End:
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,164 +0,0 @@
 | 
			
		||||
;;; magit-pull.el --- update local objects and refs  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements pull commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-pull-or-fetch nil
 | 
			
		||||
  "Whether `magit-pull' also offers some fetch suffixes."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'boolean)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-pull "magit-pull" nil t)
 | 
			
		||||
(transient-define-prefix magit-pull ()
 | 
			
		||||
  "Pull from another repository."
 | 
			
		||||
  :man-page "git-pull"
 | 
			
		||||
  [:description
 | 
			
		||||
   (lambda () (if magit-pull-or-fetch "Pull arguments" "Arguments"))
 | 
			
		||||
   ("-r" "Rebase local commits" ("-r" "--rebase"))
 | 
			
		||||
   ("-A" "Autostash" "--autostash" :level 7)]
 | 
			
		||||
  [:description
 | 
			
		||||
   (lambda ()
 | 
			
		||||
     (if-let ((branch (magit-get-current-branch)))
 | 
			
		||||
         (concat
 | 
			
		||||
          (propertize "Pull into " 'face 'transient-heading)
 | 
			
		||||
          (propertize branch       'face 'magit-branch-local)
 | 
			
		||||
          (propertize " from"      'face 'transient-heading))
 | 
			
		||||
       (propertize "Pull from" 'face 'transient-heading)))
 | 
			
		||||
   ("p" magit-pull-from-pushremote)
 | 
			
		||||
   ("u" magit-pull-from-upstream)
 | 
			
		||||
   ("e" "elsewhere"         magit-pull-branch)]
 | 
			
		||||
  ["Fetch from"
 | 
			
		||||
   :if-non-nil magit-pull-or-fetch
 | 
			
		||||
   ("f" "remotes"           magit-fetch-all-no-prune)
 | 
			
		||||
   ("F" "remotes and prune" magit-fetch-all-prune)]
 | 
			
		||||
  ["Fetch"
 | 
			
		||||
   :if-non-nil magit-pull-or-fetch
 | 
			
		||||
   ("o" "another branch"    magit-fetch-branch)
 | 
			
		||||
   ("s" "explicit refspec"  magit-fetch-refspec)
 | 
			
		||||
   ("m" "submodules"        magit-fetch-modules)]
 | 
			
		||||
  ["Configure"
 | 
			
		||||
   ("r" magit-branch.<branch>.rebase :if magit-get-current-branch)
 | 
			
		||||
   ("C" "variables..." magit-branch-configure)]
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (transient-setup 'magit-pull nil nil :scope (magit-get-current-branch)))
 | 
			
		||||
 | 
			
		||||
(defun magit-pull-arguments ()
 | 
			
		||||
  (transient-args 'magit-pull))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-pull-from-pushremote "magit-pull" nil t)
 | 
			
		||||
(transient-define-suffix magit-pull-from-pushremote (args)
 | 
			
		||||
  "Pull from the push-remote of the current branch.
 | 
			
		||||
 | 
			
		||||
With a prefix argument or when the push-remote is either not
 | 
			
		||||
configured or unusable, then let the user first configure the
 | 
			
		||||
push-remote."
 | 
			
		||||
  :if 'magit-get-current-branch
 | 
			
		||||
  :description 'magit-pull--pushbranch-description
 | 
			
		||||
  (interactive (list (magit-pull-arguments)))
 | 
			
		||||
  (pcase-let ((`(,branch ,remote)
 | 
			
		||||
               (magit--select-push-remote "pull from there")))
 | 
			
		||||
    (run-hooks 'magit-credential-hook)
 | 
			
		||||
    (magit-run-git-async "pull" args remote branch)))
 | 
			
		||||
 | 
			
		||||
(defun magit-pull--pushbranch-description ()
 | 
			
		||||
  ;; Also used by `magit-rebase-onto-pushremote'.
 | 
			
		||||
  (let* ((branch (magit-get-current-branch))
 | 
			
		||||
         (target (magit-get-push-branch branch t))
 | 
			
		||||
         (remote (magit-get-push-remote branch))
 | 
			
		||||
         (v (magit--push-remote-variable branch t)))
 | 
			
		||||
    (cond
 | 
			
		||||
     (target)
 | 
			
		||||
     ((member remote (magit-list-remotes))
 | 
			
		||||
      (format "%s, replacing non-existent" v))
 | 
			
		||||
     (remote
 | 
			
		||||
      (format "%s, replacing invalid" v))
 | 
			
		||||
     (t
 | 
			
		||||
      (format "%s, setting that" v)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-pull-from-upstream "magit-pull" nil t)
 | 
			
		||||
(transient-define-suffix magit-pull-from-upstream (args)
 | 
			
		||||
  "Pull from the upstream of the current branch.
 | 
			
		||||
 | 
			
		||||
With a prefix argument or when the upstream is either not
 | 
			
		||||
configured or unusable, then let the user first configure
 | 
			
		||||
the upstream."
 | 
			
		||||
  :if 'magit-get-current-branch
 | 
			
		||||
  :description 'magit-pull--upstream-description
 | 
			
		||||
  (interactive (list (magit-pull-arguments)))
 | 
			
		||||
  (let* ((branch (or (magit-get-current-branch)
 | 
			
		||||
                     (user-error "No branch is checked out")))
 | 
			
		||||
         (remote (magit-get "branch" branch "remote"))
 | 
			
		||||
         (merge  (magit-get "branch" branch "merge")))
 | 
			
		||||
    (when (or current-prefix-arg
 | 
			
		||||
              (not (or (magit-get-upstream-branch branch)
 | 
			
		||||
                       (magit--unnamed-upstream-p remote merge))))
 | 
			
		||||
      (magit-set-upstream-branch
 | 
			
		||||
       branch (magit-read-upstream-branch
 | 
			
		||||
               branch (format "Set upstream of %s and pull from there" branch)))
 | 
			
		||||
      (setq remote (magit-get "branch" branch "remote"))
 | 
			
		||||
      (setq merge  (magit-get "branch" branch "merge")))
 | 
			
		||||
    (run-hooks 'magit-credential-hook)
 | 
			
		||||
    (magit-run-git-with-editor "pull" args remote merge)))
 | 
			
		||||
 | 
			
		||||
(defun magit-pull--upstream-description ()
 | 
			
		||||
  (when-let ((branch (magit-get-current-branch)))
 | 
			
		||||
    (or (magit-get-upstream-branch branch)
 | 
			
		||||
        (let ((remote (magit-get "branch" branch "remote"))
 | 
			
		||||
              (merge  (magit-get "branch" branch "merge"))
 | 
			
		||||
              (u (magit--propertize-face "@{upstream}" 'bold)))
 | 
			
		||||
          (cond
 | 
			
		||||
           ((magit--unnamed-upstream-p remote merge)
 | 
			
		||||
            (format "%s of %s"
 | 
			
		||||
                    (magit--propertize-face merge 'magit-branch-remote)
 | 
			
		||||
                    (magit--propertize-face remote 'bold)))
 | 
			
		||||
           ((magit--valid-upstream-p remote merge)
 | 
			
		||||
            (concat u ", replacing non-existent"))
 | 
			
		||||
           ((or remote merge)
 | 
			
		||||
            (concat u ", replacing invalid"))
 | 
			
		||||
           (t
 | 
			
		||||
            (concat u ", setting that")))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-pull-branch (source args)
 | 
			
		||||
  "Pull from a branch read in the minibuffer."
 | 
			
		||||
  (interactive (list (magit-read-remote-branch "Pull" nil nil nil t)
 | 
			
		||||
                     (magit-pull-arguments)))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (pcase-let ((`(,remote . ,branch)
 | 
			
		||||
               (magit-get-tracked source)))
 | 
			
		||||
    (magit-run-git-with-editor "pull" args remote branch)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-pull)
 | 
			
		||||
;;; magit-pull.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,331 +0,0 @@
 | 
			
		||||
;;; magit-push.el --- update remote objects and refs  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2008-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements push commands.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
(require 'magit)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-push "magit-push" nil t)
 | 
			
		||||
(transient-define-prefix magit-push ()
 | 
			
		||||
  "Push to another repository."
 | 
			
		||||
  :man-page "git-push"
 | 
			
		||||
  ["Arguments"
 | 
			
		||||
   ("-f" "Force with lease" (nil "--force-with-lease"))
 | 
			
		||||
   ("-F" "Force"            ("-f" "--force"))
 | 
			
		||||
   ("-h" "Disable hooks"    "--no-verify")
 | 
			
		||||
   ("-n" "Dry run"          ("-n" "--dry-run"))
 | 
			
		||||
   (5 "-u" "Set upstream"   "--set-upstream")
 | 
			
		||||
   (7 "-t" "Follow tags"    "--follow-tags")]
 | 
			
		||||
  [:if magit-get-current-branch
 | 
			
		||||
   :description (lambda ()
 | 
			
		||||
                  (format (propertize "Push %s to" 'face 'transient-heading)
 | 
			
		||||
                          (propertize (magit-get-current-branch)
 | 
			
		||||
                                      'face 'magit-branch-local)))
 | 
			
		||||
   ("p" magit-push-current-to-pushremote)
 | 
			
		||||
   ("u" magit-push-current-to-upstream)
 | 
			
		||||
   ("e" "elsewhere" magit-push-current)]
 | 
			
		||||
  ["Push"
 | 
			
		||||
   [("o" "another branch"    magit-push-other)
 | 
			
		||||
    ("r" "explicit refspecs" magit-push-refspecs)
 | 
			
		||||
    ("m" "matching branches" magit-push-matching)]
 | 
			
		||||
   [("T" "a tag"             magit-push-tag)
 | 
			
		||||
    ("t" "all tags"          magit-push-tags)
 | 
			
		||||
    (6 "n" "a note ref"      magit-push-notes-ref)]]
 | 
			
		||||
  ["Configure"
 | 
			
		||||
   ("C" "Set variables..."  magit-branch-configure)])
 | 
			
		||||
 | 
			
		||||
(defun magit-push-arguments ()
 | 
			
		||||
  (transient-args 'magit-push))
 | 
			
		||||
 | 
			
		||||
(defun magit-git-push (branch target args)
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  ;; If the remote branch already exists, then we do not have to
 | 
			
		||||
  ;; qualify the target, which we prefer to avoid doing because
 | 
			
		||||
  ;; using the default namespace is wrong in obscure cases.
 | 
			
		||||
  (pcase-let ((namespace (if (magit-get-tracked target) "" "refs/heads/"))
 | 
			
		||||
              (`(,remote . ,target)
 | 
			
		||||
               (magit-split-branch-name target)))
 | 
			
		||||
    (magit-run-git-async "push" "-v" args remote
 | 
			
		||||
                         (format "%s:%s%s" branch namespace target))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-push-current-to-pushremote "magit-push" nil t)
 | 
			
		||||
(transient-define-suffix magit-push-current-to-pushremote (args)
 | 
			
		||||
  "Push the current branch to its push-remote.
 | 
			
		||||
 | 
			
		||||
When the push-remote is not configured, then read the push-remote
 | 
			
		||||
from the user, set it, and then push to it.  With a prefix
 | 
			
		||||
argument the push-remote can be changed before pushed to it."
 | 
			
		||||
  :if 'magit-get-current-branch
 | 
			
		||||
  :description 'magit-push--pushbranch-description
 | 
			
		||||
  (interactive (list (magit-push-arguments)))
 | 
			
		||||
  (pcase-let ((`(,branch ,remote)
 | 
			
		||||
               (magit--select-push-remote "push there")))
 | 
			
		||||
    (run-hooks 'magit-credential-hook)
 | 
			
		||||
    (magit-run-git-async "push" "-v" args remote
 | 
			
		||||
                         (format "refs/heads/%s:refs/heads/%s"
 | 
			
		||||
                                 branch branch)))) ; see #3847 and #3872
 | 
			
		||||
 | 
			
		||||
(defun magit-push--pushbranch-description ()
 | 
			
		||||
  (let* ((branch (magit-get-current-branch))
 | 
			
		||||
         (target (magit-get-push-branch branch t))
 | 
			
		||||
         (remote (magit-get-push-remote branch))
 | 
			
		||||
         (v (magit--push-remote-variable branch t)))
 | 
			
		||||
    (cond
 | 
			
		||||
     (target)
 | 
			
		||||
     ((member remote (magit-list-remotes))
 | 
			
		||||
      (format "%s, creating it"
 | 
			
		||||
              (magit--propertize-face (concat remote "/" branch)
 | 
			
		||||
                                      'magit-branch-remote)))
 | 
			
		||||
     (remote
 | 
			
		||||
      (format "%s, replacing invalid" v))
 | 
			
		||||
     (t
 | 
			
		||||
      (format "%s, setting that" v)))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload (autoload 'magit-push-current-to-upstream "magit-push" nil t)
 | 
			
		||||
(transient-define-suffix magit-push-current-to-upstream (args)
 | 
			
		||||
  "Push the current branch to its upstream branch.
 | 
			
		||||
 | 
			
		||||
With a prefix argument or when the upstream is either not
 | 
			
		||||
configured or unusable, then let the user first configure
 | 
			
		||||
the upstream."
 | 
			
		||||
  :if 'magit-get-current-branch
 | 
			
		||||
  :description 'magit-push--upstream-description
 | 
			
		||||
  (interactive (list (magit-push-arguments)))
 | 
			
		||||
  (let* ((branch (or (magit-get-current-branch)
 | 
			
		||||
                     (user-error "No branch is checked out")))
 | 
			
		||||
         (remote (magit-get "branch" branch "remote"))
 | 
			
		||||
         (merge  (magit-get "branch" branch "merge")))
 | 
			
		||||
    (when (or current-prefix-arg
 | 
			
		||||
              (not (or (magit-get-upstream-branch branch)
 | 
			
		||||
                       (magit--unnamed-upstream-p remote merge)
 | 
			
		||||
                       (magit--valid-upstream-p remote merge))))
 | 
			
		||||
      (let* ((branches (-union (--map (concat it "/" branch)
 | 
			
		||||
                                      (magit-list-remotes))
 | 
			
		||||
                               (magit-list-remote-branch-names)))
 | 
			
		||||
             (upstream (magit-completing-read
 | 
			
		||||
                        (format "Set upstream of %s and push there" branch)
 | 
			
		||||
                        branches nil nil nil 'magit-revision-history
 | 
			
		||||
                        (or (car (member (magit-remote-branch-at-point) branches))
 | 
			
		||||
                            (car (member "origin/master" branches)))))
 | 
			
		||||
             (upstream (or (magit-get-tracked upstream)
 | 
			
		||||
                           (magit-split-branch-name upstream))))
 | 
			
		||||
        (setq remote (car upstream))
 | 
			
		||||
        (setq merge  (cdr upstream))
 | 
			
		||||
        (unless (string-prefix-p "refs/" merge)
 | 
			
		||||
          ;; User selected a non-existent remote-tracking branch.
 | 
			
		||||
          ;; It is very likely, but not certain, that this is the
 | 
			
		||||
          ;; correct thing to do.  It is even more likely that it
 | 
			
		||||
          ;; is what the user wants to happen.
 | 
			
		||||
          (setq merge (concat "refs/heads/" merge))))
 | 
			
		||||
      (cl-pushnew "--set-upstream" args :test #'equal))
 | 
			
		||||
    (run-hooks 'magit-credential-hook)
 | 
			
		||||
    (magit-run-git-async "push" "-v" args remote (concat branch ":" merge))))
 | 
			
		||||
 | 
			
		||||
(defun magit-push--upstream-description ()
 | 
			
		||||
  (when-let ((branch (magit-get-current-branch)))
 | 
			
		||||
    (or (magit-get-upstream-branch branch)
 | 
			
		||||
        (let ((remote (magit-get "branch" branch "remote"))
 | 
			
		||||
              (merge  (magit-get "branch" branch "merge"))
 | 
			
		||||
              (u (magit--propertize-face "@{upstream}" 'bold)))
 | 
			
		||||
          (cond
 | 
			
		||||
           ((magit--unnamed-upstream-p remote merge)
 | 
			
		||||
            (format "%s as %s"
 | 
			
		||||
                    (magit--propertize-face remote 'bold)
 | 
			
		||||
                    (magit--propertize-face merge 'magit-branch-remote)))
 | 
			
		||||
           ((magit--valid-upstream-p remote merge)
 | 
			
		||||
            (format "%s creating %s"
 | 
			
		||||
                    (magit--propertize-face remote 'magit-branch-remote)
 | 
			
		||||
                    (magit--propertize-face merge 'magit-branch-remote)))
 | 
			
		||||
           ((or remote merge)
 | 
			
		||||
            (concat u ", creating it and replacing invalid"))
 | 
			
		||||
           (t
 | 
			
		||||
            (concat u ", creating it")))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-current (target args)
 | 
			
		||||
  "Push the current branch to a branch read in the minibuffer."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (--if-let (magit-get-current-branch)
 | 
			
		||||
       (list (magit-read-remote-branch (format "Push %s to" it)
 | 
			
		||||
                                       nil nil it 'confirm)
 | 
			
		||||
             (magit-push-arguments))
 | 
			
		||||
     (user-error "No branch is checked out")))
 | 
			
		||||
  (magit-git-push (magit-get-current-branch) target args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-other (source target args)
 | 
			
		||||
  "Push an arbitrary branch or commit somewhere.
 | 
			
		||||
Both the source and the target are read in the minibuffer."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((source (magit-read-local-branch-or-commit "Push")))
 | 
			
		||||
     (list source
 | 
			
		||||
           (magit-read-remote-branch
 | 
			
		||||
            (format "Push %s to" source) nil
 | 
			
		||||
            (if (magit-local-branch-p source)
 | 
			
		||||
                (or (magit-get-push-branch source)
 | 
			
		||||
                    (magit-get-upstream-branch source))
 | 
			
		||||
              (and (magit-rev-ancestor-p source "HEAD")
 | 
			
		||||
                   (or (magit-get-push-branch)
 | 
			
		||||
                       (magit-get-upstream-branch))))
 | 
			
		||||
            source 'confirm)
 | 
			
		||||
           (magit-push-arguments))))
 | 
			
		||||
  (magit-git-push source target args))
 | 
			
		||||
 | 
			
		||||
(defvar magit-push-refspecs-history nil)
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-refspecs (remote refspecs args)
 | 
			
		||||
  "Push one or multiple REFSPECS to a REMOTE.
 | 
			
		||||
Both the REMOTE and the REFSPECS are read in the minibuffer.  To
 | 
			
		||||
use multiple REFSPECS, separate them with commas.  Completion is
 | 
			
		||||
only available for the part before the colon, or when no colon
 | 
			
		||||
is used."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (list (magit-read-remote "Push to remote")
 | 
			
		||||
         (split-string (magit-completing-read-multiple
 | 
			
		||||
                        "Push refspec,s"
 | 
			
		||||
                        (cons "HEAD" (magit-list-local-branch-names))
 | 
			
		||||
                        nil nil 'magit-push-refspecs-history)
 | 
			
		||||
                       crm-default-separator t)
 | 
			
		||||
         (magit-push-arguments)))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" "-v" args remote refspecs))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-matching (remote &optional args)
 | 
			
		||||
  "Push all matching branches to another repository.
 | 
			
		||||
If multiple remotes exist, then read one from the user.
 | 
			
		||||
If just one exists, use that without requiring confirmation."
 | 
			
		||||
  (interactive (list (magit-read-remote "Push matching branches to" nil t)
 | 
			
		||||
                     (magit-push-arguments)))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" "-v" args remote ":"))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-tags (remote &optional args)
 | 
			
		||||
  "Push all tags to another repository.
 | 
			
		||||
If only one remote exists, then push to that.  Otherwise prompt
 | 
			
		||||
for a remote, offering the remote configured for the current
 | 
			
		||||
branch as default."
 | 
			
		||||
  (interactive (list (magit-read-remote "Push tags to remote" nil t)
 | 
			
		||||
                     (magit-push-arguments)))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" remote "--tags" args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-tag (tag remote &optional args)
 | 
			
		||||
  "Push a tag to another repository."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let  ((tag (magit-read-tag "Push tag")))
 | 
			
		||||
     (list tag (magit-read-remote (format "Push %s to remote" tag) nil t)
 | 
			
		||||
           (magit-push-arguments))))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" remote tag args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-notes-ref (ref remote &optional args)
 | 
			
		||||
  "Push a notes ref to another repository."
 | 
			
		||||
  (interactive
 | 
			
		||||
   (let ((note (magit-notes-read-ref "Push notes" nil nil)))
 | 
			
		||||
     (list note
 | 
			
		||||
           (magit-read-remote (format "Push %s to remote" note) nil t)
 | 
			
		||||
           (magit-push-arguments))))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" remote ref args))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-implicitly (args)
 | 
			
		||||
  "Push somewhere without using an explicit refspec.
 | 
			
		||||
 | 
			
		||||
This command simply runs \"git push -v [ARGS]\".  ARGS are the
 | 
			
		||||
arguments specified in the popup buffer.  No explicit refspec
 | 
			
		||||
arguments are used.  Instead the behavior depends on at least
 | 
			
		||||
these Git variables: `push.default', `remote.pushDefault',
 | 
			
		||||
`branch.<branch>.pushRemote', `branch.<branch>.remote',
 | 
			
		||||
`branch.<branch>.merge', and `remote.<remote>.push'.
 | 
			
		||||
 | 
			
		||||
The function `magit-push-implicitly--desc' attempts to predict
 | 
			
		||||
what this command will do.  The value it returns is displayed in
 | 
			
		||||
the popup buffer."
 | 
			
		||||
  (interactive (list (magit-push-arguments)))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" "-v" args))
 | 
			
		||||
 | 
			
		||||
(defun magit-push-implicitly--desc ()
 | 
			
		||||
  (let ((default (magit-get "push.default")))
 | 
			
		||||
    (unless (equal default "nothing")
 | 
			
		||||
      (or (when-let ((remote (or (magit-get-remote)
 | 
			
		||||
                                 (magit-remote-p "origin")))
 | 
			
		||||
                     (refspec (magit-get "remote" remote "push")))
 | 
			
		||||
            (format "%s using %s"
 | 
			
		||||
                    (magit--propertize-face remote 'magit-branch-remote)
 | 
			
		||||
                    (magit--propertize-face refspec 'bold)))
 | 
			
		||||
          (--when-let (and (not (magit-get-push-branch))
 | 
			
		||||
                           (magit-get-upstream-branch))
 | 
			
		||||
            (format "%s aka %s\n"
 | 
			
		||||
                    (magit-branch-set-face it)
 | 
			
		||||
                    (magit--propertize-face "@{upstream}" 'bold)))
 | 
			
		||||
          (--when-let (magit-get-push-branch)
 | 
			
		||||
            (format "%s aka %s\n"
 | 
			
		||||
                    (magit-branch-set-face it)
 | 
			
		||||
                    (magit--propertize-face "pushRemote" 'bold)))
 | 
			
		||||
          (--when-let (magit-get-@{push}-branch)
 | 
			
		||||
            (format "%s aka %s\n"
 | 
			
		||||
                    (magit-branch-set-face it)
 | 
			
		||||
                    (magit--propertize-face "@{push}" 'bold)))
 | 
			
		||||
          (format "using %s (%s is %s)\n"
 | 
			
		||||
                  (magit--propertize-face "git push"     'bold)
 | 
			
		||||
                  (magit--propertize-face "push.default" 'bold)
 | 
			
		||||
                  (magit--propertize-face default        'bold))))))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-push-to-remote (remote args)
 | 
			
		||||
  "Push to REMOTE without using an explicit refspec.
 | 
			
		||||
The REMOTE is read in the minibuffer.
 | 
			
		||||
 | 
			
		||||
This command simply runs \"git push -v [ARGS] REMOTE\".  ARGS
 | 
			
		||||
are the arguments specified in the popup buffer.  No refspec
 | 
			
		||||
arguments are used.  Instead the behavior depends on at least
 | 
			
		||||
these Git variables: `push.default', `remote.pushDefault',
 | 
			
		||||
`branch.<branch>.pushRemote', `branch.<branch>.remote',
 | 
			
		||||
`branch.<branch>.merge', and `remote.<remote>.push'."
 | 
			
		||||
  (interactive (list (magit-read-remote "Push to remote")
 | 
			
		||||
                     (magit-push-arguments)))
 | 
			
		||||
  (run-hooks 'magit-credential-hook)
 | 
			
		||||
  (magit-run-git-async "push" "-v" args remote))
 | 
			
		||||
 | 
			
		||||
(defun magit-push-to-remote--desc ()
 | 
			
		||||
  (format "using %s\n" (magit--propertize-face "git push <remote>" 'bold)))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-push)
 | 
			
		||||
;;; magit-push.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -1,213 +0,0 @@
 | 
			
		||||
;;; magit-reflog.el --- inspect ref history  -*- lexical-binding: t -*-
 | 
			
		||||
 | 
			
		||||
;; Copyright (C) 2010-2020  The Magit Project Contributors
 | 
			
		||||
;;
 | 
			
		||||
;; You should have received a copy of the AUTHORS.md file which
 | 
			
		||||
;; lists all contributors.  If not, see http://magit.vc/authors.
 | 
			
		||||
 | 
			
		||||
;; Author: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
 | 
			
		||||
 | 
			
		||||
;; Magit 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, or (at your option)
 | 
			
		||||
;; any later version.
 | 
			
		||||
;;
 | 
			
		||||
;; Magit 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 Magit.  If not, see http://www.gnu.org/licenses.
 | 
			
		||||
 | 
			
		||||
;;; Commentary:
 | 
			
		||||
 | 
			
		||||
;; This library implements support for looking at Git reflogs.
 | 
			
		||||
 | 
			
		||||
;;; Code:
 | 
			
		||||
 | 
			
		||||
(require 'magit-core)
 | 
			
		||||
(require 'magit-log)
 | 
			
		||||
 | 
			
		||||
(eval-when-compile
 | 
			
		||||
  (require 'subr-x))
 | 
			
		||||
 | 
			
		||||
;;; Options
 | 
			
		||||
 | 
			
		||||
(defcustom magit-reflog-limit 256
 | 
			
		||||
  "Maximal number of entries initially shown in reflog buffers.
 | 
			
		||||
The limit in the current buffer can be changed using \"+\"
 | 
			
		||||
and \"-\"."
 | 
			
		||||
  :package-version '(magit . "3.0.0")
 | 
			
		||||
  :group 'magit-commands
 | 
			
		||||
  :type 'number)
 | 
			
		||||
 | 
			
		||||
(defcustom magit-reflog-margin
 | 
			
		||||
  (list (nth 0 magit-log-margin)
 | 
			
		||||
        (nth 1 magit-log-margin)
 | 
			
		||||
        'magit-log-margin-width nil
 | 
			
		||||
        (nth 4 magit-log-margin))
 | 
			
		||||
  "Format of the margin in `magit-reflog-mode' buffers.
 | 
			
		||||
 | 
			
		||||
The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH).
 | 
			
		||||
 | 
			
		||||
If INIT is non-nil, then the margin is shown initially.
 | 
			
		||||
STYLE controls how to format the author or committer date.
 | 
			
		||||
  It can be one of `age' (to show the age of the commit),
 | 
			
		||||
  `age-abbreviated' (to abbreviate the time unit to a character),
 | 
			
		||||
  or a string (suitable for `format-time-string') to show the
 | 
			
		||||
  actual date.  Option `magit-log-margin-show-committer-date'
 | 
			
		||||
  controls which date is being displayed.
 | 
			
		||||
WIDTH controls the width of the margin.  This exists for forward
 | 
			
		||||
  compatibility and currently the value should not be changed.
 | 
			
		||||
AUTHOR controls whether the name of the author is also shown by
 | 
			
		||||
  default.
 | 
			
		||||
AUTHOR-WIDTH has to be an integer.  When the name of the author
 | 
			
		||||
  is shown, then this specifies how much space is used to do so."
 | 
			
		||||
  :package-version '(magit . "2.9.0")
 | 
			
		||||
  :group 'magit-log
 | 
			
		||||
  :group 'magit-margin
 | 
			
		||||
  :type magit-log-margin--custom-type
 | 
			
		||||
  :initialize 'magit-custom-initialize-reset
 | 
			
		||||
  :set-after '(magit-log-margin)
 | 
			
		||||
  :set (apply-partially #'magit-margin-set-variable 'magit-reflog-mode))
 | 
			
		||||
 | 
			
		||||
;;; Faces
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-commit '((t :foreground "green"))
 | 
			
		||||
  "Face for commit commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-amend '((t :foreground "magenta"))
 | 
			
		||||
  "Face for amend commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-merge '((t :foreground "green"))
 | 
			
		||||
  "Face for merge, checkout and branch commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-checkout '((t :foreground "blue"))
 | 
			
		||||
  "Face for checkout commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-reset '((t :foreground "red"))
 | 
			
		||||
  "Face for reset commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-rebase '((t :foreground "magenta"))
 | 
			
		||||
  "Face for rebase commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-cherry-pick '((t :foreground "green"))
 | 
			
		||||
  "Face for cherry-pick commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-remote '((t :foreground "cyan"))
 | 
			
		||||
  "Face for pull and clone commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
(defface magit-reflog-other '((t :foreground "cyan"))
 | 
			
		||||
  "Face for other commands in reflogs."
 | 
			
		||||
  :group 'magit-faces)
 | 
			
		||||
 | 
			
		||||
;;; Commands
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-reflog-current ()
 | 
			
		||||
  "Display the reflog of the current branch.
 | 
			
		||||
If `HEAD' is detached, then show the reflog for that instead."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-reflog-setup-buffer (or (magit-get-current-branch) "HEAD")))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-reflog-other (ref)
 | 
			
		||||
  "Display the reflog of a branch or another ref."
 | 
			
		||||
  (interactive (list (magit-read-local-branch-or-ref "Show reflog for")))
 | 
			
		||||
  (magit-reflog-setup-buffer ref))
 | 
			
		||||
 | 
			
		||||
;;;###autoload
 | 
			
		||||
(defun magit-reflog-head ()
 | 
			
		||||
  "Display the `HEAD' reflog."
 | 
			
		||||
  (interactive)
 | 
			
		||||
  (magit-reflog-setup-buffer "HEAD"))
 | 
			
		||||
 | 
			
		||||
;;; Mode
 | 
			
		||||
 | 
			
		||||
(defvar magit-reflog-mode-map
 | 
			
		||||
  (let ((map (make-sparse-keymap)))
 | 
			
		||||
    (set-keymap-parent map magit-log-mode-map)
 | 
			
		||||
    (define-key map "\C-c\C-n" 'undefined)
 | 
			
		||||
    (define-key map "L" 'magit-margin-settings)
 | 
			
		||||
    map)
 | 
			
		||||
  "Keymap for `magit-reflog-mode'.")
 | 
			
		||||
 | 
			
		||||
(define-derived-mode magit-reflog-mode magit-mode "Magit Reflog"
 | 
			
		||||
  "Mode for looking at Git reflog.
 | 
			
		||||
 | 
			
		||||
This mode is documented in info node `(magit)Reflog'.
 | 
			
		||||
 | 
			
		||||
\\<magit-mode-map>\
 | 
			
		||||
Type \\[magit-refresh] to refresh the current buffer.
 | 
			
		||||
Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \
 | 
			
		||||
to visit the commit at point.
 | 
			
		||||
 | 
			
		||||
Type \\[magit-cherry-pick] to apply the commit at point.
 | 
			
		||||
Type \\[magit-reset] to reset `HEAD' to the commit at point.
 | 
			
		||||
 | 
			
		||||
\\{magit-reflog-mode-map}"
 | 
			
		||||
  :group 'magit-log
 | 
			
		||||
  (hack-dir-local-variables-non-file-buffer))
 | 
			
		||||
 | 
			
		||||
(defun magit-reflog-setup-buffer (ref)
 | 
			
		||||
  (require 'magit)
 | 
			
		||||
  (magit-setup-buffer #'magit-reflog-mode nil
 | 
			
		||||
    (magit-buffer-refname ref)
 | 
			
		||||
    (magit-buffer-log-args (list (format "-n%s" magit-reflog-limit)))))
 | 
			
		||||
 | 
			
		||||
(defun magit-reflog-refresh-buffer ()
 | 
			
		||||
  (magit-set-header-line-format (concat "Reflog for " magit-buffer-refname))
 | 
			
		||||
  (magit-insert-section (reflogbuf)
 | 
			
		||||
    (magit-git-wash (apply-partially 'magit-log-wash-log 'reflog)
 | 
			
		||||
      "reflog" "show" "--format=%h%x00%aN%x00%gd%x00%gs" "--date=raw"
 | 
			
		||||
      magit-buffer-log-args magit-buffer-refname "--")))
 | 
			
		||||
 | 
			
		||||
(cl-defmethod magit-buffer-value (&context (major-mode magit-reflog-mode))
 | 
			
		||||
  magit-buffer-refname)
 | 
			
		||||
 | 
			
		||||
(defvar magit-reflog-labels
 | 
			
		||||
  '(("commit"      . magit-reflog-commit)
 | 
			
		||||
    ("amend"       . magit-reflog-amend)
 | 
			
		||||
    ("merge"       . magit-reflog-merge)
 | 
			
		||||
    ("checkout"    . magit-reflog-checkout)
 | 
			
		||||
    ("branch"      . magit-reflog-checkout)
 | 
			
		||||
    ("reset"       . magit-reflog-reset)
 | 
			
		||||
    ("rebase"      . magit-reflog-rebase)
 | 
			
		||||
    ("cherry-pick" . magit-reflog-cherry-pick)
 | 
			
		||||
    ("initial"     . magit-reflog-commit)
 | 
			
		||||
    ("pull"        . magit-reflog-remote)
 | 
			
		||||
    ("clone"       . magit-reflog-remote)
 | 
			
		||||
    ("autosave"    . magit-reflog-commit)
 | 
			
		||||
    ("restart"     . magit-reflog-reset)))
 | 
			
		||||
 | 
			
		||||
(defun magit-reflog-format-subject (subject)
 | 
			
		||||
  (let* ((match (string-match magit-reflog-subject-re subject))
 | 
			
		||||
         (command (and match (match-string 1 subject)))
 | 
			
		||||
         (option  (and match (match-string 2 subject)))
 | 
			
		||||
         (type    (and match (match-string 3 subject)))
 | 
			
		||||
         (label (if (string= command "commit")
 | 
			
		||||
                    (or type command)
 | 
			
		||||
                  command))
 | 
			
		||||
         (text (if (string= command "commit")
 | 
			
		||||
                   label
 | 
			
		||||
                 (mapconcat #'identity
 | 
			
		||||
                            (delq nil (list command option type))
 | 
			
		||||
                            " "))))
 | 
			
		||||
    (format "%-16s "
 | 
			
		||||
            (magit--propertize-face
 | 
			
		||||
             text (or (cdr (assoc label magit-reflog-labels))
 | 
			
		||||
                      'magit-reflog-other)))))
 | 
			
		||||
 | 
			
		||||
;;; _
 | 
			
		||||
(provide 'magit-reflog)
 | 
			
		||||
;;; magit-reflog.el ends here
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user