@@ -25,6 +25,7 @@ static enum {
2525static struct strbuf charset = STRBUF_INIT ;
2626static int patch_lines ;
2727static struct strbuf * * p_hdr_data , * * s_hdr_data ;
28+ static int use_scissors ;
2829
2930#define MAX_HDR_PARSED 10
3031#define MAX_BOUNDARIES 5
@@ -712,6 +713,56 @@ static inline int patchbreak(const struct strbuf *line)
712713 return 0 ;
713714}
714715
716+ static int is_scissors_line (const struct strbuf * line )
717+ {
718+ size_t i , len = line -> len ;
719+ int scissors = 0 , gap = 0 ;
720+ int first_nonblank = -1 ;
721+ int last_nonblank = 0 , visible , perforation = 0 , in_perforation = 0 ;
722+ const char * buf = line -> buf ;
723+
724+ for (i = 0 ; i < len ; i ++ ) {
725+ if (isspace (buf [i ])) {
726+ if (in_perforation ) {
727+ perforation ++ ;
728+ gap ++ ;
729+ }
730+ continue ;
731+ }
732+ last_nonblank = i ;
733+ if (first_nonblank < 0 )
734+ first_nonblank = i ;
735+ if (buf [i ] == '-' ) {
736+ in_perforation = 1 ;
737+ perforation ++ ;
738+ continue ;
739+ }
740+ if (i + 1 < len &&
741+ (!memcmp (buf + i , ">8" , 2 ) || !memcmp (buf + i , "8<" , 2 ))) {
742+ in_perforation = 1 ;
743+ perforation += 2 ;
744+ scissors += 2 ;
745+ i ++ ;
746+ continue ;
747+ }
748+ in_perforation = 0 ;
749+ }
750+
751+ /*
752+ * The mark must be at least 8 bytes long (e.g. "-- >8 --").
753+ * Even though there can be arbitrary cruft on the same line
754+ * (e.g. "cut here"), in order to avoid misidentification, the
755+ * perforation must occupy more than a third of the visible
756+ * width of the line, and dashes and scissors must occupy more
757+ * than half of the perforation.
758+ */
759+
760+ visible = last_nonblank - first_nonblank + 1 ;
761+ return (scissors && 8 <= visible &&
762+ visible < perforation * 3 &&
763+ gap * 2 < perforation );
764+ }
765+
715766static int handle_commit_msg (struct strbuf * line )
716767{
717768 static int still_looking = 1 ;
@@ -723,14 +774,33 @@ static int handle_commit_msg(struct strbuf *line)
723774 strbuf_ltrim (line );
724775 if (!line -> len )
725776 return 0 ;
726- if ((still_looking = check_header (line , s_hdr_data , 0 )) != 0 )
777+ still_looking = check_header (line , s_hdr_data , 0 );
778+ if (still_looking )
727779 return 0 ;
728780 }
729781
730782 /* normalize the log message to UTF-8. */
731783 if (metainfo_charset )
732784 convert_to_utf8 (line , charset .buf );
733785
786+ if (use_scissors && is_scissors_line (line )) {
787+ int i ;
788+ rewind (cmitmsg );
789+ ftruncate (fileno (cmitmsg ), 0 );
790+ still_looking = 1 ;
791+
792+ /*
793+ * We may have already read "secondary headers"; purge
794+ * them to give ourselves a clean restart.
795+ */
796+ for (i = 0 ; header [i ]; i ++ ) {
797+ if (s_hdr_data [i ])
798+ strbuf_release (s_hdr_data [i ]);
799+ s_hdr_data [i ] = NULL ;
800+ }
801+ return 0 ;
802+ }
803+
734804 if (patchbreak (line )) {
735805 fclose (cmitmsg );
736806 cmitmsg = NULL ;
@@ -885,12 +955,9 @@ static void handle_info(void)
885955 fprintf (fout , "\n" );
886956}
887957
888- static int mailinfo (FILE * in , FILE * out , int ks , const char * encoding ,
889- const char * msg , const char * patch )
958+ static int mailinfo (FILE * in , FILE * out , const char * msg , const char * patch )
890959{
891960 int peek ;
892- keep_subject = ks ;
893- metainfo_charset = encoding ;
894961 fin = in ;
895962 fout = out ;
896963
@@ -924,6 +991,18 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
924991 return 0 ;
925992}
926993
994+ static int git_mailinfo_config (const char * var , const char * value , void * unused )
995+ {
996+ if (prefixcmp (var , "mailinfo." ))
997+ return git_default_config (var , value , unused );
998+ if (!strcmp (var , "mailinfo.scissors" )) {
999+ use_scissors = git_config_bool (var , value );
1000+ return 0 ;
1001+ }
1002+ /* perhaps others here */
1003+ return 0 ;
1004+ }
1005+
9271006static const char mailinfo_usage [] =
9281007 "git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info" ;
9291008
@@ -934,7 +1013,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
9341013 /* NEEDSWORK: might want to do the optional .git/ directory
9351014 * discovery
9361015 */
937- git_config (git_default_config , NULL );
1016+ git_config (git_mailinfo_config , NULL );
9381017
9391018 def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8" );
9401019 metainfo_charset = def_charset ;
@@ -948,6 +1027,10 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
9481027 metainfo_charset = NULL ;
9491028 else if (!prefixcmp (argv [1 ], "--encoding=" ))
9501029 metainfo_charset = argv [1 ] + 11 ;
1030+ else if (!strcmp (argv [1 ], "--scissors" ))
1031+ use_scissors = 1 ;
1032+ else if (!strcmp (argv [1 ], "--no-scissors" ))
1033+ use_scissors = 0 ;
9511034 else
9521035 usage (mailinfo_usage );
9531036 argc -- ; argv ++ ;
@@ -956,5 +1039,5 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
9561039 if (argc != 3 )
9571040 usage (mailinfo_usage );
9581041
959- return !!mailinfo (stdin , stdout , keep_subject , metainfo_charset , argv [1 ], argv [2 ]);
1042+ return !!mailinfo (stdin , stdout , argv [1 ], argv [2 ]);
9601043}
0 commit comments