aboutsummaryrefslogtreecommitdiffhomepage
path: root/share/functions/__fish_git_prompt.fish
blob: 9591ef38689210fa6f7acb7246d3fb72d7cf3df8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
# based off of the git-prompt script that ships with git
#
# Written by Kevin Ballard <kevin@sb.org>
# Updated by Brian Gernhardt <brian@gernhardtsoftware.com>
#
# This is heavily based off of the git-prompt.bash script that ships with
# git, which is Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>.
# The act of porting the code, along with any new code, are Copyright (C) 2012
# Kevin Ballard <kevin@sb.org>.
#
# By virtue of being based on the git-prompt.bash script, this script is
# distributed under the GNU General Public License, version 2.0.
#
# This script vends a function __fish_git_prompt which takes a format string,
# exactly how the bash script works. This can be used in your fish_prompt
# function.
#
# The behavior of __fish_git_prompt is very heavily based off of the bash
# script's __git_ps1 function. As such, usage and customization is very
# similar, although some extra features are provided in this script.
# Due to differences between bash and fish, the PROMPT_COMMAND style where
# passing two or three arguments causes the fucnction to set PS1 is not
# supported.  More information on the additional features is found after the
# bash-compatable documentation.
#
# The argument to __fish_git_prompt will be displayed only if you are currently
# in a git repository. The %s token will be the name of the branch.
#
# In addition, if you set __fish_git_prompt_showdirtystate to a nonempty value,
# unstaged (*) and staged (+) changes will be shown next to the branch name.
# You can configure this per-repository with the bash.showDirtyState variable,
# which defaults to true once __fish_git_prompt_showdirtystate is enabled. The
# choice to leave the variable as 'bash' instead of renaming to 'fish' is done
# to preserve compatibility with existing configured repositories.
#
# You can also see if currently something is stashed, by setting
# __fish_git_prompt_showstashstate to a nonempty value. If something is
# stashed, then a '$' will be shown next to the branch name.
#
# If you would like to see if there are untracked files, then you can set
# __fish_git_prompt_showuntrackedfiles to a nonempty value. If there are
# untracked files, then a '%' will be shown next to the branch name. Once you
# have set __fish_git_prompt_showuntrackedfiles, you can override it on a
# per-repository basis by setting the bash.showUntrackedFiles config variable.
# As before, this variable remains named 'bash' to preserve compatibility.
#
# If you would like to see the difference between HEAD and its upstream, set
# __fish_git_prompt_showupstream to 'auto'. A "<" indicates you are behind, ">"
# indicates you are ahead, "<>" indicates you have diverged and "=" indicates
# that there is no difference. You can further control behavior by setting
# __fish_git_prompt_showupstream to a space-separated list of values:
#
#     verbose        show number of commits ahead/behind (+/-) upstream
#     name           if verbose, then also show the upstream abbrev name
#     informative    similar to verbose, but shows nothing when equal (fish only)
#     git            always compare HEAD to @{upstream}
#     svn            always compare HEAD to your SVN upstream
#     none           disables (fish only, useful with show_informative_status)
#
# By default, __fish_git_prompt will compare HEAD to your SVN upstream if it
# can find one, or @{upstream} otherwise. Once you have set
# __fish_git_prompt_showupstream, you can override it on a per-repository basis
# by setting the bash.showUpstream config variable. As before, this variable
# remains named 'bash' to preserve compatibility.
#
# If you would like to see more information about the identity of commits
# checked out as a detached HEAD, set __fish_git_prompt_describe_style to
# one of the following values:
#
#     contains      relative to newer annotated tag (v1.6.3.2~35)
#     branch        relative to newer tag or branch (master~4)
#     describe      relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
#     default       exactly matching tag
#
# If you would like a colored hint about the current dirty state, set
# __fish_git_prompt_showcolorhints to a nonempty value.  The default colors are
# based on the colored output of "git status -sb"


# __fish_git_prompt includes some additional features on top of the
# above-documented bash-compatible features:
#
#
# An "informative git prompt" mode similar to the scripts for bash and zsh
# can be activated by setting __fish_git_prompt_show_informative_status
# This works more like the "informative git prompt" scripts for bash and zsh,
# giving prompts like (master↑1↓2|●3✖4✚5…6) where master is the current branch,
# you have 1 commit your upstream doesn't and it has 2 you don't, and you have
# 3 staged, 4 unmerged, 5 dirty, and 6 untracked files.  If you have no
# changes, it displays (master|✔).
#
# Setting __fish_git_prompt_show_informative_status changes several defaults.
# The default mode for __fish_git_prompt_showupstream changes to informative
# and the following characters have their defaults changed.  (The characters
# and colors can still be customized as described below.)
#
#     upstream_prefix ()
#     upstream_ahead  (↑)
#     upstream_behind (↓)
#     stateseparator  (|)
#     dirtystate      (✚)
#     invalidstate    (✖)
#     stagedstate     (●)
#     untrackedfiles  (…)
#     cleanstate      (✔)
#
#
# The color for each component of the prompt can specified using
# __fish_git_prompt_color_<name>, where <name> is one of the following and the
# values are specified as arguments to `set_color`.  The variable
# __fish_git_prompt_color is used for any component that does not have an
# individual color set.
#
#     prefix     Anything before %s in the format string
#     suffix     Anything after  %s in the format string
#     bare       Marker for a bare repository
#     merging    Current operation (|MERGING, |REBASE, etc.)
#     branch     Branch name
#     flags      Optional flags (see below)
#     upstream   Upstream name and flags (with showupstream)
#
#
# The following optional flags have both colors, as above, and custom
# characters via __fish_git_prompt_char_<name>.  The default character is
# shown in parenthesis.  The default color for these flags can be also be set
# via the __fish_git_prompt_color_flags variable.
#
#   __fish_git_prompt_showdirtystate
#     dirtystate          unstaged changes (*)
#     stagedstate         staged changes   (+)
#     invalidstate        HEAD invalid     (#, colored as stagedstate)
#
#   __fish_git_prompt_showstashstate
#     stashstate          stashed changes  ($)
#
#   __fish_git_prompt_showuntrackedfiles
#     untrackedfiles      untracked files  (%)
#
#   __fish_git_prompt_showupstream  (all colored as upstream)
#     upstream_equal      Branch matches upstream              (=)
#     upstream_behind     Upstream has more commits            (<)
#     upstream_ahead      Branch has more commits              (>)
#     upstream_diverged   Upstream and branch have new commits (<>)
#
#   __fish_git_prompt_show_informative_status
#     (see also the flags for showdirtystate and showuntrackedfiles, above)
#     cleanstate          Working directory has no changes (✔)
#
#
# The separator between the branch name and flags can also be customized via
# __fish_git_prompt_char_stateseparator.  It can only be colored by
# __fish_git_prompt_color.  It normally defaults to a space ( ) and defaults
# to a vertical bar (|) when __fish_git_prompt_show_informative_status is set.
#
# The separator before the upstream information can be customized via
# __fish_git_prompt_char_upstream_prefix.  It is colored like the rest of
# the upstream information.  It normally defaults to nothing () and defaults
# to a space ( ) when __fish_git_prompt_showupstream contains verbose.
#
#
# Turning on __fish_git_prompt_showcolorhints changes the colors as follows to
# more closely match the behavior in bash.  Note that setting any of these
# colors manually will override these defaults.
#
#     branch            Defaults to green
#     branch_detached   New color, when head is detached, default red
#     dirtystate        Defaults to red
#     stagedstate       Defaults to green
#     flags             Defaults to --bold blue

function __fish_git_prompt_show_upstream --description "Helper function for __fish_git_prompt"
    set -l show_upstream $__fish_git_prompt_showupstream
    set -l svn_prefix # For better SVN upstream information
    set -l informative

    set -l svn_url_pattern
    set -l count
    set -l upstream git
    set -l verbose
    set -l name

    # Default to informative if show_informative_status is set
    if test -n "$__fish_git_prompt_show_informative_status"
        set informative 1
    end

    set -l svn_remote
    # get some config options from git-config
    command git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' ^/dev/null | while read -lz key value
        switch $key
            case bash.showupstream
                set show_upstream $value
                test -n "$show_upstream"
                or return
            case svn-remote.'*'.url
                set svn_remote $svn_remote $value
                # Avoid adding \| to the beginning to avoid needing #?? later
                if test -n "$svn_url_pattern"
                    set svn_url_pattern $svn_url_pattern"|$value"
                else
                    set svn_url_pattern $value
                end
                set upstream svn+git # default upstream is SVN if available, else git

                # Save the config key (without .url) for later use
                set -l remote_prefix (string replace -r '\.url$' '' -- $key)
                set svn_prefix $svn_prefix $remote_prefix
        end
    end

    # parse configuration variables
    # and clear informative default when needed
    for option in $show_upstream
        switch $option
            case git svn
                set upstream $option
                set -e informative
            case verbose
                set verbose 1
                set -e informative
            case informative
                set informative 1
            case name
                set name 1
            case none
                return
        end
    end

    # Find our upstream
    switch $upstream
        case git
            set upstream '@{upstream}'
        case svn\*
            # get the upstream from the 'git-svn-id: ...' in a commit message
            # (git-svn uses essentially the same procedure internally)
            set -l svn_upstream (git log --first-parent -1 --grep="^git-svn-id: \($svn_url_pattern\)" ^/dev/null)
            if test (count $svn_upstream) -ne 0
                echo $svn_upstream[-1] | read -l __ svn_upstream __
                set svn_upstream (string replace -r '@.*' '' -- $svn_upstream)
                set -l cur_prefix
                for i in (seq (count $svn_remote))
                    set -l remote $svn_remote[$i]
                    set -l mod_upstream (string replace "$remote" "" -- $svn_upstream)
                    if test "$svn_upstream" != "$mod_upstream"
                        # we found a valid remote
                        set svn_upstream $mod_upstream
                        set cur_prefix $svn_prefix[$i]
                        break
                    end
                end

                if test -z "$svn_upstream"
                    # default branch name for checkouts with no layout:
                    if test -n "$GIT_SVN_ID"
                        set upstream $GIT_SVN_ID
                    else
                        set upstream git-svn
                    end
                else
                    set upstream (string replace '/branches' '' -- $svn_upstream | string replace -a '/' '')

                    # Use fetch config to fix upstream
                    set -l fetch_val (command git config "$cur_prefix".fetch)
                    if test -n "$fetch_val"
                        set -l IFS :
                        echo "$fetch_val" | read -l trunk pattern
                        set upstream (string replace -r -- "/$trunk\$" '' $pattern) /$upstream
                    end
                end
            else if test $upstream = svn+git
                set upstream '@{upstream}'
            end
    end

    # Find how many commits we are ahead/behind our upstream
    set count (command git rev-list --count --left-right $upstream...HEAD ^/dev/null)

    # calculate the result
    if test -n "$verbose"
        # Verbose has a space by default
        set -l prefix "$___fish_git_prompt_char_upstream_prefix"
        # Using two underscore version to check if user explicitly set to nothing
        if not set -q __fish_git_prompt_char_upstream_prefix
            set -l prefix " "
        end

        echo $count | read -l behind ahead
        switch "$count"
            case '' # no upstream
            case "0	0" # equal to upstream
                echo "$prefix$___fish_git_prompt_char_upstream_equal"
            case "0	*" # ahead of upstream
                echo "$prefix$___fish_git_prompt_char_upstream_ahead$ahead"
            case "*	0" # behind upstream
                echo "$prefix$___fish_git_prompt_char_upstream_behind$behind"
            case '*' # diverged from upstream
                echo "$prefix$___fish_git_prompt_char_upstream_diverged$ahead-$behind"
        end
        if test -n "$count" -a -n "$name"
            echo " "(command git rev-parse --abbrev-ref "$upstream" ^/dev/null)
        end
    else if test -n "$informative"
        echo $count | read -l behind ahead
        switch "$count"
            case '' # no upstream
            case "0	0" # equal to upstream
            case "0	*" # ahead of upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead"
            case "*	0" # behind upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind$behind"
            case '*' # diverged from upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead$___fish_git_prompt_char_upstream_behind$behind"
        end
    else
        switch "$count"
            case '' # no upstream
            case "0	0" # equal to upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_equal"
            case "0	*" # ahead of upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead"
            case "*	0" # behind upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind"
            case '*' # diverged from upstream
                echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_diverged"
        end
    end
end

function __fish_git_prompt --description "Prompt function for Git"
    # If git isn't installed, there's nothing we can do
    # Return 1 so the calling prompt can deal with it
    if not command -s git >/dev/null
        return 1
    end
    set -l repo_info (command git rev-parse --git-dir --is-inside-git-dir --is-bare-repository --is-inside-work-tree HEAD ^/dev/null)
    test -n "$repo_info"
    or return

    set -l git_dir $repo_info[1]
    set -l inside_gitdir $repo_info[2]
    set -l bare_repo $repo_info[3]
    set -l inside_worktree $repo_info[4]
    set -q repo_info[5]
    and set -l sha $repo_info[5]

    set -l rbc (__fish_git_prompt_operation_branch_bare $repo_info)
    set -l r $rbc[1] # current operation
    set -l b $rbc[2] # current branch
    set -l detached $rbc[3]
    set -l w #dirty working directory
    set -l i #staged changes
    set -l s #stashes
    set -l u #untracked
    set -l c $rbc[4] # bare repository
    set -l p #upstream
    set -l informative_status

    __fish_git_prompt_validate_chars
    __fish_git_prompt_validate_colors

    set -l space "$___fish_git_prompt_color$___fish_git_prompt_char_stateseparator$___fish_git_prompt_color_done"

    if test "true" = $inside_worktree
        if test -n "$__fish_git_prompt_show_informative_status"
            set informative_status "$space"(__fish_git_prompt_informative_status)
        else
            if test -n "$__fish_git_prompt_showdirtystate"
                set -l config (command git config --bool bash.showDirtyState)
                if test "$config" != "false"
                    set w (__fish_git_prompt_dirty)
                    set i (__fish_git_prompt_staged $sha)
                end
            end

            if test -n "$__fish_git_prompt_showstashstate" -a -r $git_dir/refs/stash
                set s $___fish_git_prompt_char_stashstate
            end

            if test -n "$__fish_git_prompt_showuntrackedfiles"
                set -l config (command git config --bool bash.showUntrackedFiles)
                if test "$config" != false
                    if command git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null ^/dev/null
                        set u $___fish_git_prompt_char_untrackedfiles
                    end
                end
            end
        end

        if test -n "$__fish_git_prompt_showupstream" -o "$__fish_git_prompt_show_informative_status"
            set p (__fish_git_prompt_show_upstream)
        end
    end

    set -l branch_color $___fish_git_prompt_color_branch
    set -l branch_done $___fish_git_prompt_color_branch_done
    if test -n "$__fish_git_prompt_showcolorhints"
        if test $detached = yes
            set branch_color $___fish_git_prompt_color_branch_detached
            set branch_done $___fish_git_prompt_color_branch_detached_done
        end
    end

    if test -n "$w"
        set w "$___fish_git_prompt_color_dirtystate$w$___fish_git_prompt_color_dirtystate_done"
    end
    if test -n "$i"
        set i "$___fish_git_prompt_color_stagedstate$i$___fish_git_prompt_color_stagedstate_done"
    end
    if test -n "$s"
        set s "$___fish_git_prompt_color_stashstate$s$___fish_git_prompt_color_stashstate_done"
    end
    if test -n "$u"
        set u "$___fish_git_prompt_color_untrackedfiles$u$___fish_git_prompt_color_untrackedfiles_done"
    end
    set b (string replace refs/heads/ '' -- $b)
    if test -n "$b"
        set b "$branch_color$b$branch_done"
    end
    if test -n "$c"
        set c "$___fish_git_prompt_color_bare$c$___fish_git_prompt_color_bare_done"
    end
    if test -n "$r"
        set r "$___fish_git_prompt_color_merging$r$___fish_git_prompt_color_merging_done"
    end
    if test -n "$p"
        set p "$___fish_git_prompt_color_upstream$p$___fish_git_prompt_color_upstream_done"
    end

    # Formatting
    set -l f "$w$i$s$u"
    if test -n "$f"
        set f "$space$f"
    end
    set -l format $argv[1]
    if test -z "$format"
        set format " (%s)"
    end

    printf "%s$format%s" "$___fish_git_prompt_color_prefix" "$___fish_git_prompt_color_prefix_done$c$b$f$r$p$informative_status$___fish_git_prompt_color_suffix" "$___git_ps_color_suffix_done"
end

### helper functions

function __fish_git_prompt_staged --description "__fish_git_prompt helper, tells whether or not the current branch has staged files"
    set -l sha $argv[1]

    set -l staged

    if test -n "$sha"
        command git diff-index --cached --quiet HEAD --
        or set staged $___fish_git_prompt_char_stagedstate
    else
        set staged $___fish_git_prompt_char_invalidstate
    end
    echo $staged
end

function __fish_git_prompt_dirty --description "__fish_git_prompt helper, tells whether or not the current branch has tracked, modified files"
    set -l dirty

    set -l os
    command git diff --no-ext-diff --quiet --exit-code
    set os $status
    if test $os -ne 0
        set dirty $___fish_git_prompt_char_dirtystate
    end
    echo $dirty
end

set -g ___fish_git_prompt_status_order stagedstate invalidstate dirtystate untrackedfiles

function __fish_git_prompt_informative_status

    set -l changedFiles (command git diff --name-status | cut -c 1-2)
    set -l stagedFiles (command git diff --staged --name-status | cut -c 1-2)

    set -l dirtystate (math (count $changedFiles) - (count (echo $changedFiles | grep "U")))
    set -l invalidstate (count (echo $stagedFiles | grep "U"))
    set -l stagedstate (math (count $stagedFiles) - $invalidstate)
    set -l untrackedfiles (count (command git ls-files --others --exclude-standard))

    set -l info

    if [ (math $dirtystate + $invalidstate + $stagedstate + $untrackedfiles) = 0 ]
        set info $___fish_git_prompt_color_cleanstate$___fish_git_prompt_char_cleanstate$___fish_git_prompt_color_cleanstate_done
    else
        for i in $___fish_git_prompt_status_order
            if [ $$i != "0" ]
                set -l color_var ___fish_git_prompt_color_$i
                set -l color_done_var ___fish_git_prompt_color_{$i}_done
                set -l symbol_var ___fish_git_prompt_char_$i

                set -l color $$color_var
                set -l color_done $$color_done_var
                set -l symbol $$symbol_var

                set -l count

                if not set -q __fish_git_prompt_hide_$i
                    set count $$i
                end

                set info "$info$color$symbol$count$color_done"
            end
        end
    end

    echo $info

end

# Keeping these together avoids many duplicated checks
function __fish_git_prompt_operation_branch_bare --description "__fish_git_prompt helper, returns the current Git operation and branch"
    # This function is passed the full repo_info array
    set -l git_dir $argv[1]
    set -l inside_gitdir $argv[2]
    set -l bare_repo $argv[3]
    set -q argv[5]
    and set -l sha $argv[5]

    set -l branch
    set -l operation
    set -l detached no
    set -l bare
    set -l step
    set -l total
    set -l os

    if test -d $git_dir/rebase-merge
        set branch (cat $git_dir/rebase-merge/head-name ^/dev/null)
        set step (cat $git_dir/rebase-merge/msgnum ^/dev/null)
        set total (cat $git_dir/rebase-merge/end ^/dev/null)
        if test -f $git_dir/rebase-merge/interactive
            set operation "|REBASE-i"
        else
            set operation "|REBASE-m"
        end
    else
        if test -d $git_dir/rebase-apply
            set step (cat $git_dir/rebase-apply/next ^/dev/null)
            set total (cat $git_dir/rebase-apply/last ^/dev/null)
            if test -f $git_dir/rebase-apply/rebasing
                set branch (cat $git_dir/rebase-apply/head-name ^/dev/null)
                set operation "|REBASE"
            else if test -f $git_dir/rebase-apply/applying
                set operation "|AM"
            else
                set operation "|AM/REBASE"
            end
        else if test -f $git_dir/MERGE_HEAD
            set operation "|MERGING"
        else if test -f $git_dir/CHERRY_PICK_HEAD
            set operation "|CHERRY-PICKING"
        else if test -f $git_dir/REVERT_HEAD
            set operation "|REVERTING"
        else if test -f $git_dir/BISECT_LOG
            set operation "|BISECTING"
        end
    end

    if test -n "$step" -a -n "$total"
        set operation "$operation $step/$total"
    end

    if test -z "$branch"
        set branch (command git symbolic-ref HEAD ^/dev/null; set os $status)
        if test $os -ne 0
            set detached yes
            set branch (switch "$__fish_git_prompt_describe_style"
						case contains
							command git describe --contains HEAD
						case branch
							command git describe --contains --all HEAD
						case describe
							command git describe HEAD
						case default '*'
							command git describe --tags --exact-match HEAD
						end ^/dev/null; set os $status)
            if test $os -ne 0
                # Shorten the sha ourselves to 8 characters - this should be good for most repositories,
                # and even for large ones it should be good for most commits
                if set -q sha
                    set branch (string match -r '^.{8}' -- $sha)...
                else
                    set branch unknown
                end
            end
            set branch "($branch)"
        end
    end

    if test "true" = $inside_gitdir
        if test "true" = $bare_repo
            set bare "BARE:"
        else
            # Let user know they're inside the git dir of a non-bare repo
            set branch "GIT_DIR!"
        end
    end

    echo $operation
    echo $branch
    echo $detached
    echo $bare
end

function __fish_git_prompt_set_char
    set -l user_variable_name "$argv[1]"
    set -l char $argv[2]
    set -l user_variable $$user_variable_name

    if test (count $argv) -ge 3
        if test -n "$__fish_git_prompt_show_informative_status"
            set char $argv[3]
        end
    end

    set -l variable _$user_variable_name
    set -l variable_done "$variable"_done

    if not set -q $variable
        set -g $variable (set -q $user_variable_name; and echo $user_variable; or echo $char)
    end
end

function __fish_git_prompt_validate_chars --description "__fish_git_prompt helper, checks char variables"

    __fish_git_prompt_set_char __fish_git_prompt_char_cleanstate '✔'
    __fish_git_prompt_set_char __fish_git_prompt_char_dirtystate '*' '✚'
    __fish_git_prompt_set_char __fish_git_prompt_char_invalidstate '#' '✖'
    __fish_git_prompt_set_char __fish_git_prompt_char_stagedstate '+' '●'
    __fish_git_prompt_set_char __fish_git_prompt_char_stashstate '$'
    __fish_git_prompt_set_char __fish_git_prompt_char_stateseparator ' ' '|'
    __fish_git_prompt_set_char __fish_git_prompt_char_untrackedfiles '%' '…'
    __fish_git_prompt_set_char __fish_git_prompt_char_upstream_ahead '>' '↑'
    __fish_git_prompt_set_char __fish_git_prompt_char_upstream_behind '<' '↓'
    __fish_git_prompt_set_char __fish_git_prompt_char_upstream_diverged '<>'
    __fish_git_prompt_set_char __fish_git_prompt_char_upstream_equal '='
    __fish_git_prompt_set_char __fish_git_prompt_char_upstream_prefix ''

end

function __fish_git_prompt_set_color
    set -l user_variable_name "$argv[1]"
    set -l user_variable $$user_variable_name
    set -l user_variable_bright

    set -l default default_done
    switch (count $argv)
        case 1 # No defaults given, use prompt color
            set default $___fish_git_prompt_color
            set default_done $___fish_git_prompt_color_done
        case 2 # One default given, use normal for done
            set default "$argv[2]"
            set default_done (set_color normal)
        case 3 # Both defaults given
            set default "$argv[2]"
            set default_done "$argv[3]"
    end

    set -l variable _$user_variable_name
    set -l variable_done "$variable"_done

    if not set -q $variable
        if test -n "$user_variable"
            set -g $variable (set_color $user_variable)
            set -g $variable_done (set_color normal)
        else
            set -g $variable $default
            set -g $variable_done $default_done
        end
    end

end


function __fish_git_prompt_validate_colors --description "__fish_git_prompt helper, checks color variables"

    # Base color defaults to nothing (must be done first)
    __fish_git_prompt_set_color __fish_git_prompt_color '' ''

    # Normal colors
    __fish_git_prompt_set_color __fish_git_prompt_color_prefix
    __fish_git_prompt_set_color __fish_git_prompt_color_suffix
    __fish_git_prompt_set_color __fish_git_prompt_color_bare
    __fish_git_prompt_set_color __fish_git_prompt_color_merging
    __fish_git_prompt_set_color __fish_git_prompt_color_cleanstate
    __fish_git_prompt_set_color __fish_git_prompt_color_invalidstate
    __fish_git_prompt_set_color __fish_git_prompt_color_upstream

    # Colors with defaults with showcolorhints
    if test -n "$__fish_git_prompt_showcolorhints"
        __fish_git_prompt_set_color __fish_git_prompt_color_flags (set_color --bold blue)
        __fish_git_prompt_set_color __fish_git_prompt_color_branch (set_color green)
        __fish_git_prompt_set_color __fish_git_prompt_color_dirtystate (set_color red)
        __fish_git_prompt_set_color __fish_git_prompt_color_stagedstate (set_color green)
    else
        __fish_git_prompt_set_color __fish_git_prompt_color_flags
        __fish_git_prompt_set_color __fish_git_prompt_color_branch
        __fish_git_prompt_set_color __fish_git_prompt_color_dirtystate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
        __fish_git_prompt_set_color __fish_git_prompt_color_stagedstate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
    end

    # Branch_detached has a default, but is only used with showcolorhints
    __fish_git_prompt_set_color __fish_git_prompt_color_branch_detached (set_color red)

    # Colors that depend on flags color
    __fish_git_prompt_set_color __fish_git_prompt_color_stashstate $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done
    __fish_git_prompt_set_color __fish_git_prompt_color_untrackedfiles $___fish_git_prompt_color_flags $___fish_git_prompt_color_flags_done

end

set -l varargs
for var in repaint describe_style show_informative_status showdirtystate showstashstate showuntrackedfiles showupstream
    set varargs $varargs --on-variable __fish_git_prompt_$var
end
function __fish_git_prompt_repaint $varargs --description "Event handler, repaints prompt when functionality changes"
    if status --is-interactive
        if test $argv[3] = __fish_git_prompt_show_informative_status
            # Clear characters that have different defaults with/without informative status
            for name in cleanstate dirtystate invalidstate stagedstate stateseparator untrackedfiles upstream_ahead upstream_behind
                set -e ___fish_git_prompt_char_$name
            end
        end

        commandline -f repaint ^/dev/null
    end
end

set -l varargs
for var in '' _prefix _suffix _bare _merging _cleanstate _invalidstate _upstream _flags _branch _dirtystate _stagedstate _branch_detached _stashstate _untrackedfiles
    set varargs $varargs --on-variable __fish_git_prompt_color$var
end
set varargs $varargs --on-variable __fish_git_prompt_showcolorhints
function __fish_git_prompt_repaint_color $varargs --description "Event handler, repaints prompt when any color changes"
    if status --is-interactive
        set -l var $argv[3]
        set -e _$var
        set -e _{$var}_done
        if test $var = __fish_git_prompt_color -o $var = __fish_git_prompt_color_flags -o $var = __fish_git_prompt_showcolorhints
            # reset all the other colors too
            for name in prefix suffix bare merging branch dirtystate stagedstate invalidstate stashstate untrackedfiles upstream flags
                set -e ___fish_git_prompt_color_$name
                set -e ___fish_git_prompt_color_{$name}_done
            end
        end
        commandline -f repaint ^/dev/null
    end
end

set -l varargs
for var in cleanstate dirtystate invalidstate stagedstate stashstate stateseparator untrackedfiles upstream_ahead upstream_behind upstream_diverged upstream_equal upstream_prefix
    set varargs $varargs --on-variable __fish_git_prompt_char_$var
end
function __fish_git_prompt_repaint_char $varargs --description "Event handler, repaints prompt when any char changes"
    if status --is-interactive
        set -e _$argv[3]
        commandline -f repaint ^/dev/null
    end
end