Explorar el Código

Adds new GitLens custom view

main
Eric Amodio hace 7 años
padre
commit
9782a81e46
Se han modificado 69 ficheros con 949 adiciones y 610 borrados
  1. +5
    -1
      images/dark/icon-add.svg
  2. +4
    -0
      images/dark/icon-branch.svg
  3. +2
    -2
      images/dark/icon-commit.svg
  4. +4
    -0
      images/dark/icon-download.svg
  5. +4
    -0
      images/dark/icon-history.svg
  6. +2
    -3
      images/dark/icon-refresh.svg
  7. +4
    -0
      images/dark/icon-remote.svg
  8. +4
    -0
      images/dark/icon-repo.svg
  9. +4
    -0
      images/dark/icon-search.svg
  10. +4
    -0
      images/dark/icon-stash.svg
  11. +4
    -0
      images/dark/icon-upload.svg
  12. +5
    -1
      images/light/icon-add.svg
  13. +4
    -0
      images/light/icon-branch.svg
  14. +2
    -2
      images/light/icon-commit.svg
  15. +4
    -0
      images/light/icon-download.svg
  16. +4
    -0
      images/light/icon-history.svg
  17. +2
    -3
      images/light/icon-refresh.svg
  18. +4
    -0
      images/light/icon-remote.svg
  19. +4
    -0
      images/light/icon-repo.svg
  20. +4
    -0
      images/light/icon-search.svg
  21. +4
    -0
      images/light/icon-stash.svg
  22. +4
    -0
      images/light/icon-upload.svg
  23. +160
    -125
      package.json
  24. +13
    -0
      src/commands/common.ts
  25. +12
    -2
      src/commands/copyMessageToClipboard.ts
  26. +12
    -2
      src/commands/copyShaToClipboard.ts
  27. +10
    -4
      src/commands/diffWithPrevious.ts
  28. +11
    -1
      src/commands/openBranchInRemote.ts
  29. +2
    -3
      src/commands/openCommitInRemote.ts
  30. +11
    -1
      src/commands/openFileInRemote.ts
  31. +21
    -14
      src/commands/openInRemote.ts
  32. +0
    -7
      src/commands/showCommitSearch.ts
  33. +6
    -6
      src/commands/showFileHistory.ts
  34. +2
    -3
      src/commands/showQuickCommitDetails.ts
  35. +13
    -1
      src/commands/showQuickCommitFileDetails.ts
  36. +5
    -10
      src/commands/stashApply.ts
  37. +4
    -8
      src/commands/stashDelete.ts
  38. +2
    -10
      src/configuration.ts
  39. +10
    -4
      src/constants.ts
  40. +2
    -2
      src/currentLineController.ts
  41. +2
    -8
      src/extension.ts
  42. +3
    -1
      src/git/git.ts
  43. +11
    -15
      src/git/remotes/provider.ts
  44. +4
    -4
      src/gitContentProvider.ts
  45. +5
    -6
      src/gitRevisionCodeLensProvider.ts
  46. +18
    -15
      src/quickPicks/commitDetails.ts
  47. +24
    -24
      src/quickPicks/commitFileDetails.ts
  48. +1
    -1
      src/quickPicks/fileHistory.ts
  49. +8
    -8
      src/quickPicks/remotes.ts
  50. +16
    -7
      src/views/branchHistoryNode.ts
  51. +11
    -4
      src/views/branchesNode.ts
  52. +17
    -5
      src/views/commitFileNode.ts
  53. +21
    -7
      src/views/commitNode.ts
  54. +20
    -5
      src/views/explorerNode.ts
  55. +7
    -2
      src/views/explorerNodes.ts
  56. +0
    -89
      src/views/fileHistoryExplorer.ts
  57. +11
    -6
      src/views/fileHistoryNode.ts
  58. +125
    -36
      src/views/gitExplorer.ts
  59. +30
    -0
      src/views/historyNode.ts
  60. +35
    -0
      src/views/remoteNode.ts
  61. +35
    -0
      src/views/remotesNode.ts
  62. +8
    -5
      src/views/repositoryNode.ts
  63. +0
    -46
      src/views/stashCommitNode.ts
  64. +0
    -75
      src/views/stashExplorer.ts
  65. +14
    -0
      src/views/stashFileNode.ts
  66. +21
    -15
      src/views/stashNode.ts
  67. +34
    -0
      src/views/stashesNode.ts
  68. +37
    -11
      src/views/statusNode.ts
  69. +53
    -0
      src/views/statusUpstreamNode.ts

+ 5
- 1
images/dark/icon-add.svg Ver fichero

@ -1 +1,5 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><rect height="11" width="3" y="3" x="7" fill="#C5C5C5"/><rect height="3" width="11" y="7" x="3" fill="#C5C5C5"/></svg>
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect fill="#C5C5C5" x="6.5" y="5.5" width="3" height="11"/>
<rect fill="#C5C5C5" x="2.5" y="9.5" width="11" height="3"/>
</svg>

+ 4
- 0
images/dark/icon-branch.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m13,8c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -2,0.89 -2,2c0,0.73 0.41,1.38 1,1.72l0,0.3c-0.02,0.52 -0.23,0.98 -0.63,1.38c-0.4,0.4 -0.86,0.61 -1.38,0.63c-0.83,0.02 -1.48,0.16 -2,0.45l0,-4.76c0.59,-0.34 1,-0.98 1,-1.72c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -1.99,0.89 -1.99,2c0,0.73 0.41,1.38 1,1.72l0,6.56c-0.59,0.35 -1,0.99 -1,1.72c0,1.11 0.89,2 2,2c1.11,0 2,-0.89 2,-2c0,-0.53 -0.2,-1 -0.53,-1.36c0.09,-0.06 0.48,-0.41 0.59,-0.47c0.25,-0.11 0.56,-0.17 0.94,-0.17c1.05,-0.05 1.95,-0.45 2.75,-1.25c0.8,-0.8 1.2,-1.98 1.25,-3.02l-0.02,0c0.61,-0.36 1.02,-1 1.02,-1.73l0,0zm-8,-3.2c0.66,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2c-0.65,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2l0,0zm0,12.41c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0zm6,-8c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0z" />
</svg>

+ 2
- 2
images/dark/icon-commit.svg Ver fichero

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256" height="256" viewBox="0 0 14 16" xml:space="preserve">
<path fill="#C5C5C5" d="M10.86 7c-.45-1.72-2-3-3.86-3-1.86 0-3.41 1.28-3.86 3H0v2h3.14c.45 1.72 2 3 3.86 3 1.86 0 3.41-1.28 3.86-3H14V7h-3.14zM7 10.2c-1.22 0-2.2-.98-2.2-2.2 0-1.22.98-2.2 2.2-2.2 1.22 0 2.2.98 2.2 2.2 0 1.22-.98 2.2-2.2 2.2z"></path>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m11.86,10c-0.45,-1.72 -2,-3 -3.86,-3c-1.86,0 -3.41,1.28 -3.86,3l-3.14,0l0,2l3.14,0c0.45,1.72 2,3 3.86,3c1.86,0 3.41,-1.28 3.86,-3l3.14,0l0,-2l-3.14,0zm-3.86,3.2c-1.22,0 -2.2,-0.98 -2.2,-2.2c0,-1.22 0.98,-2.2 2.2,-2.2c1.22,0 2.2,0.98 2.2,2.2c0,1.22 -0.98,2.2 -2.2,2.2z"></path>
</svg>

+ 4
- 0
images/dark/icon-download.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m9,15l2,0l-3,3l-3,-3l2,0l0,-5l2,0l0,5l0,0zm3,-8c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

+ 4
- 0
images/dark/icon-history.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m9,16l-2,0l0,-7l5,0l0,2l-3,0l0,5l0,0zm-1,-12c-2.19,0 -4.13,1.02 -5.41,2.59l-1.59,-1.59l0,4l4,0l-1.5,-1.5c1.05,-1.33 2.67,-2.2 4.5,-2.2c3.14,0 5.7,2.56 5.7,5.7c0,3.14 -2.56,5.7 -5.7,5.7c-3.14,0 -5.7,-2.56 -5.7,-5.7c0,-0.34 0.03,-0.67 0.09,-1l-1.31,0c-0.05,0.33 -0.08,0.66 -0.08,1c0,3.86 3.14,7 7,7c3.86,0 7,-3.14 7,-7c0,-3.86 -3.14,-7 -7,-7l0,0z" />
</svg>

+ 2
- 3
images/dark/icon-refresh.svg Ver fichero

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
<path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3a2.98 2.98 0 0 1-2.107-.868 2.98 2.98 0 0 1-.873-2.111 3.004 3.004 0 0 1 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012L13.115 4.1 8.196 0H7.059v2.404A6.759 6.759 0 0 0 .938 9.125c0 1.809.707 3.508 1.986 4.782a6.707 6.707 0 0 0 4.784 1.988 6.758 6.758 0 0 0 6.75-6.75 6.741 6.741 0 0 0-1.007-3.536z" fill="#2D2D30"/>
<path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4a3.986 3.986 0 0 1-2.817-1.164 3.987 3.987 0 0 1-1.163-2.815c0-2.206 1.794-4 4-4l.351.025v1.85S9.685 5.679 9.69 5.682l1.869-1.577-3.5-2.917v2.218l-.371-.03a5.75 5.75 0 0 0-4.055 9.826 5.75 5.75 0 0 0 9.826-4.056 5.725 5.725 0 0 0-.859-3.012z" fill="#C5C5C5"/>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.901149,9.091851l-0.094,0.071c-0.269,0.333 -0.746,1.096 -0.91,2.375c0.057,0.277 0.092,0.495 0.092,0.545c0,2.206 -1.794,4 -4,4a3.986,3.986 0 0 1 -2.817,-1.164a3.987,3.987 0 0 1 -1.163,-2.815c0,-2.206 1.794,-4 4,-4l0.351,0.025l0,1.85s1.626,-1.342 1.631,-1.339l1.869,-1.577l-3.5,-2.917l0,2.218l-0.371,-0.03a5.75,5.75 0 0 0 -4.055,9.826a5.75,5.75 0 0 0 9.826,-4.056a5.725,5.725 0 0 0 -0.859,-3.012z" />
</svg>

+ 4
- 0
images/dark/icon-remote.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m12.519592,15.157073l-9.039184,0c-1.367793,0 -2.480539,-1.112828 -2.480539,-2.480622s1.112746,-2.480539 2.480539,-2.480539l0.281314,0c0.349178,-0.47173 0.888523,-0.771191 1.476341,-0.815025c0.321917,-1.471535 1.619609,-2.537962 3.165139,-2.537962c1.221543,0 2.341663,0.699516 2.889377,1.772488c0.083027,-0.008618 0.166386,-0.012926 0.250076,-0.012926c1.190221,0 2.194667,0.874105 2.378785,2.027867c0.670514,0.460047 1.07869,1.225023 1.07869,2.046096c0,1.367793 -1.112828,2.480622 -2.480539,2.480622z" />
</svg>

+ 4
- 0
images/dark/icon-repo.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
</svg>

+ 4
- 0
images/dark/icon-search.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m14.414133,16.199437l-3.415492,-3.433421c0.627518,-0.878526 0.995065,-1.945307 0.995065,-3.110698c0,-2.967265 -2.411463,-5.378728 -5.378728,-5.378728c-2.967265,0 -5.378728,2.411463 -5.378728,5.378728c0,2.967265 2.411463,5.378728 5.378728,5.378728c1.165391,0 2.223207,-0.367546 3.110698,-0.995065l3.433421,3.415492c0.170326,0.179291 0.403405,0.268936 0.627518,0.268936c0.224114,0 0.466156,-0.080681 0.627518,-0.268936c0.349617,-0.349617 0.349617,-0.914384 0,-1.264001l0,0.008965zm-7.799155,-2.330782c-2.321817,0 -4.213337,-1.891519 -4.213337,-4.213337c0,-2.321817 1.891519,-4.213337 4.213337,-4.213337c2.321817,0 4.213337,1.891519 4.213337,4.213337c0,2.321817 -1.891519,4.213337 -4.213337,4.213337l0,0z" />
</svg>

+ 4
- 0
images/dark/icon-stash.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="22px">
<path fill="#C5C5C5" d="m14.687501,11.955358l-1.079554,-6.821251c-0.076429,-0.458572 -0.477679,-0.821607 -0.955357,-0.821607l-9.30518,0c-0.477679,0 -0.878929,0.363036 -0.955357,0.821607l-1.079554,6.821251l0,4.776787c0,0.525447 0.429911,0.955357 0.955357,0.955357l11.464288,0c0.525447,0 0.955357,-0.429911 0.955357,-0.955357l0,-4.776787l0,0zm-3.133572,0.525447l-0.420357,0.850268c-0.162411,0.324821 -0.496786,0.535 -0.869375,0.535l-4.547501,0c-0.363036,0 -0.687857,-0.210179 -0.850268,-0.525447l-0.420357,-0.869375c-0.162411,-0.315268 -0.496786,-0.525447 -0.850268,-0.525447l-1.327947,0l0.955357,-6.687501l9.553573,0l0.955357,6.687501l-1.318393,0c-0.372589,0 -0.697411,0.210179 -0.869375,0.525447l0.009554,0.009554z" />
</svg>

+ 4
- 0
images/dark/icon-upload.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#C5C5C5" d="m7,12l-2,0l3,-3l3,3l-2,0l0,5l-2,0l0,-5l0,0zm5,-4c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

+ 5
- 1
images/light/icon-add.svg Ver fichero

@ -1 +1,5 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><rect height="11" width="3" y="3" x="7" fill="#424242"/><rect height="3" width="11" y="7" x="3" fill="#424242"/></svg>
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect fill="#424242" x="6.5" y="5.5" width="3" height="11"/>
<rect fill="#424242" x="2.5" y="9.5" width="11" height="3"/>
</svg>

+ 4
- 0
images/light/icon-branch.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m13,8c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -2,0.89 -2,2c0,0.73 0.41,1.38 1,1.72l0,0.3c-0.02,0.52 -0.23,0.98 -0.63,1.38c-0.4,0.4 -0.86,0.61 -1.38,0.63c-0.83,0.02 -1.48,0.16 -2,0.45l0,-4.76c0.59,-0.34 1,-0.98 1,-1.72c0,-1.11 -0.89,-2 -2,-2c-1.11,0 -1.99,0.89 -1.99,2c0,0.73 0.41,1.38 1,1.72l0,6.56c-0.59,0.35 -1,0.99 -1,1.72c0,1.11 0.89,2 2,2c1.11,0 2,-0.89 2,-2c0,-0.53 -0.2,-1 -0.53,-1.36c0.09,-0.06 0.48,-0.41 0.59,-0.47c0.25,-0.11 0.56,-0.17 0.94,-0.17c1.05,-0.05 1.95,-0.45 2.75,-1.25c0.8,-0.8 1.2,-1.98 1.25,-3.02l-0.02,0c0.61,-0.36 1.02,-1 1.02,-1.73l0,0zm-8,-3.2c0.66,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2c-0.65,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2l0,0zm0,12.41c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0zm6,-8c-0.66,0 -1.2,-0.55 -1.2,-1.2c0,-0.65 0.55,-1.2 1.2,-1.2c0.65,0 1.2,0.55 1.2,1.2c0,0.65 -0.55,1.2 -1.2,1.2l0,0z" />
</svg>

+ 2
- 2
images/light/icon-commit.svg Ver fichero

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256" height="256" viewBox="0 0 14 16" xml:space="preserve">
<path fill="#6c6c6c" d="M10.86 7c-.45-1.72-2-3-3.86-3-1.86 0-3.41 1.28-3.86 3H0v2h3.14c.45 1.72 2 3 3.86 3 1.86 0 3.41-1.28 3.86-3H14V7h-3.14zM7 10.2c-1.22 0-2.2-.98-2.2-2.2 0-1.22.98-2.2 2.2-2.2 1.22 0 2.2.98 2.2 2.2 0 1.22-.98 2.2-2.2 2.2z"></path>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m11.86,10c-0.45,-1.72 -2,-3 -3.86,-3c-1.86,0 -3.41,1.28 -3.86,3l-3.14,0l0,2l3.14,0c0.45,1.72 2,3 3.86,3c1.86,0 3.41,-1.28 3.86,-3l3.14,0l0,-2l-3.14,0zm-3.86,3.2c-1.22,0 -2.2,-0.98 -2.2,-2.2c0,-1.22 0.98,-2.2 2.2,-2.2c1.22,0 2.2,0.98 2.2,2.2c0,1.22 -0.98,2.2 -2.2,2.2z"></path>
</svg>

+ 4
- 0
images/light/icon-download.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m9,15l2,0l-3,3l-3,-3l2,0l0,-5l2,0l0,5l0,0zm3,-8c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

+ 4
- 0
images/light/icon-history.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m9,16l-2,0l0,-7l5,0l0,2l-3,0l0,5l0,0zm-1,-12c-2.19,0 -4.13,1.02 -5.41,2.59l-1.59,-1.59l0,4l4,0l-1.5,-1.5c1.05,-1.33 2.67,-2.2 4.5,-2.2c3.14,0 5.7,2.56 5.7,5.7c0,3.14 -2.56,5.7 -5.7,5.7c-3.14,0 -5.7,-2.56 -5.7,-5.7c0,-0.34 0.03,-0.67 0.09,-1l-1.31,0c-0.05,0.33 -0.08,0.66 -0.08,1c0,3.86 3.14,7 7,7c3.86,0 7,-3.14 7,-7c0,-3.86 -3.14,-7 -7,-7l0,0z" />
</svg>

+ 2
- 3
images/light/icon-refresh.svg Ver fichero

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
<path d='M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3a2.98 2.98 0 0 1-2.107-.868 2.98 2.98 0 0 1-.873-2.111 3.004 3.004 0 0 1 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012L13.115 4.1 8.196 0H7.059v2.404A6.759 6.759 0 0 0 .938 9.125c0 1.809.707 3.508 1.986 4.782a6.707 6.707 0 0 0 4.784 1.988 6.758 6.758 0 0 0 6.75-6.75 6.741 6.741 0 0 0-1.007-3.536z' fill='#F6F6F6'/>
<path d='M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4a3.986 3.986 0 0 1-2.817-1.164 3.987 3.987 0 0 1-1.163-2.815c0-2.206 1.794-4 4-4l.351.025v1.85S9.685 5.679 9.69 5.682l1.869-1.577-3.5-2.917v2.218l-.371-.03a5.75 5.75 0 0 0-4.055 9.826 5.75 5.75 0 0 0 9.826-4.056 5.725 5.725 0 0 0-.859-3.012z' fill='#424242'/>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.901149,9.091851l-0.094,0.071c-0.269,0.333 -0.746,1.096 -0.91,2.375c0.057,0.277 0.092,0.495 0.092,0.545c0,2.206 -1.794,4 -4,4a3.986,3.986 0 0 1 -2.817,-1.164a3.987,3.987 0 0 1 -1.163,-2.815c0,-2.206 1.794,-4 4,-4l0.351,0.025l0,1.85s1.626,-1.342 1.631,-1.339l1.869,-1.577l-3.5,-2.917l0,2.218l-0.371,-0.03a5.75,5.75 0 0 0 -4.055,9.826a5.75,5.75 0 0 0 9.826,-4.056a5.725,5.725 0 0 0 -0.859,-3.012z" />
</svg>

+ 4
- 0
images/light/icon-remote.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m12.519592,15.157073l-9.039184,0c-1.367793,0 -2.480539,-1.112828 -2.480539,-2.480622s1.112746,-2.480539 2.480539,-2.480539l0.281314,0c0.349178,-0.47173 0.888523,-0.771191 1.476341,-0.815025c0.321917,-1.471535 1.619609,-2.537962 3.165139,-2.537962c1.221543,0 2.341663,0.699516 2.889377,1.772488c0.083027,-0.008618 0.166386,-0.012926 0.250076,-0.012926c1.190221,0 2.194667,0.874105 2.378785,2.027867c0.670514,0.460047 1.07869,1.225023 1.07869,2.046096c0,1.367793 -1.112828,2.480622 -2.480539,2.480622z" />
</svg>

+ 4
- 0
images/light/icon-repo.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m6,12l-1,0l0,-1l1,0l0,1l0,0zm0,-3l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm0,-2l-1,0l0,1l1,0l0,-1l0,0zm8,-1l0,12c0,0.55 -0.45,1 -1,1l-5,0l0,2l-1.5,-1.5l-1.5,1.5l0,-2l-2,0c-0.55,0 -1,-0.45 -1,-1l0,-12c0,-0.55 0.45,-1 1,-1l10,0c0.55,0 1,0.45 1,1l0,0zm-1,10l-10,0l0,2l2,0l0,-1l3,0l0,1l5,0l0,-2l0,0zm0,-10l-9,0l0,9l9,0l0,-9l0,0z" />
</svg>

+ 4
- 0
images/light/icon-search.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m14.414133,16.199437l-3.415492,-3.433421c0.627518,-0.878526 0.995065,-1.945307 0.995065,-3.110698c0,-2.967265 -2.411463,-5.378728 -5.378728,-5.378728c-2.967265,0 -5.378728,2.411463 -5.378728,5.378728c0,2.967265 2.411463,5.378728 5.378728,5.378728c1.165391,0 2.223207,-0.367546 3.110698,-0.995065l3.433421,3.415492c0.170326,0.179291 0.403405,0.268936 0.627518,0.268936c0.224114,0 0.466156,-0.080681 0.627518,-0.268936c0.349617,-0.349617 0.349617,-0.914384 0,-1.264001l0,0.008965zm-7.799155,-2.330782c-2.321817,0 -4.213337,-1.891519 -4.213337,-4.213337c0,-2.321817 1.891519,-4.213337 4.213337,-4.213337c2.321817,0 4.213337,1.891519 4.213337,4.213337c0,2.321817 -1.891519,4.213337 -4.213337,4.213337l0,0z" />
</svg>

+ 4
- 0
images/light/icon-stash.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="22px">
<path fill="#424242" d="m14.687501,11.955358l-1.079554,-6.821251c-0.076429,-0.458572 -0.477679,-0.821607 -0.955357,-0.821607l-9.30518,0c-0.477679,0 -0.878929,0.363036 -0.955357,0.821607l-1.079554,6.821251l0,4.776787c0,0.525447 0.429911,0.955357 0.955357,0.955357l11.464288,0c0.525447,0 0.955357,-0.429911 0.955357,-0.955357l0,-4.776787l0,0zm-3.133572,0.525447l-0.420357,0.850268c-0.162411,0.324821 -0.496786,0.535 -0.869375,0.535l-4.547501,0c-0.363036,0 -0.687857,-0.210179 -0.850268,-0.525447l-0.420357,-0.869375c-0.162411,-0.315268 -0.496786,-0.525447 -0.850268,-0.525447l-1.327947,0l0.955357,-6.687501l9.553573,0l0.955357,6.687501l-1.318393,0c-0.372589,0 -0.697411,0.210179 -0.869375,0.525447l0.009554,0.009554z" />
</svg>

+ 4
- 0
images/light/icon-upload.svg Ver fichero

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="16" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path fill="#424242" d="m7,12l-2,0l3,-3l3,3l-2,0l0,5l-2,0l0,-5l0,0zm5,-4c0,-0.44 -0.91,-3 -4.5,-3c-2.42,0 -4.5,1.92 -4.5,4c-1.98,0 -3,1.52 -3,3c0,1.53 1,3 3,3l3,0l0,-1.3l-3,0c-1.62,0 -1.7,-1.42 -1.7,-1.7c0,-0.17 0.05,-1.7 1.7,-1.7l1.3,0l0,-1.3c0,-1.39 1.56,-2.7 3.2,-2.7c2.55,0 3.13,1.55 3.2,1.8l0,1.2l1.3,0c0.81,0 2.7,0.22 2.7,2.2c0,2.09 -2.25,2.2 -2.7,2.2l-2,0l0,1.3l2,0c2.08,0 4,-1.16 4,-3.5c0,-2.44 -1.92,-3.5 -4,-3.5l0,0z" />
</svg>

+ 160
- 125
package.json Ver fichero

@ -413,20 +413,34 @@
"default": null,
"description": "Specifies how all absolute dates will be formatted by default\nSee https://momentjs.com/docs/#/displaying/format/ for valid formats"
},
"gitlens.fileHistoryExplorer.commitFormat": {
"gitlens.gitExplorer.view": {
"type": "string",
"default": "repository",
"enum": [
"history",
"repository"
],
"description": "Specifies the starting view (mode) of the `GitLens` custom view\n `history` - shows the commit history of the active file\n `repository` - shows a repository explorer"
},
"gitlens.gitExplorer.commitFormat": {
"type": "string",
"default": "${message} \u00a0\u2022\u00a0 ${authorAgo} \u00a0\u2022\u00a0 ${id}",
"description": "Specifies the format of committed changes in the `Git File History` explorer\nAvailable tokens\n ${id} - commit id\n ${author} - commit author\n ${message} - commit message\n ${ago} - relative commit date (e.g. 1 day ago)\n ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)\n ${authorAgo} - commit author, relative commit date\nSee https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting"
"description": "Specifies the format of committed changes in the `GitLens` custom view\nAvailable tokens\n ${id} - commit id\n ${author} - commit author\n ${message} - commit message\n ${ago} - relative commit date (e.g. 1 day ago)\n ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)\n ${authorAgo} - commit author, relative commit date\nSee https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting"
},
"gitlens.gitExplorer.commitFileFormat": {
"type": "string",
"default": "${filePath}",
"description": "Specifies the format of a committed file in the `GitLens` custom view\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
},
"gitlens.stashExplorer.stashFormat": {
"gitlens.gitExplorer.stashFormat": {
"type": "string",
"default": "${message}",
"description": "Specifies the format of stashed changes in the `Git Stashes` explorer\nAvailable tokens\n ${id} - commit id\n ${author} - commit author\n ${message} - commit message\n ${ago} - relative commit date (e.g. 1 day ago)\n ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)\n ${authorAgo} - commit author, relative commit date\nSee https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting"
"description": "Specifies the format of stashed changes in the `GitLens` custom view\nAvailable tokens\n ${id} - commit id\n ${author} - commit author\n ${message} - commit message\n ${ago} - relative commit date (e.g. 1 day ago)\n ${date} - formatted commit date (format specified by `gitlens.statusBar.dateFormat`)\n ${authorAgo} - commit author, relative commit date\nSee https://github.com/eamodio/vscode-gitlens/wiki/Advanced-Formatting for advanced formatting"
},
"gitlens.stashExplorer.stashFileFormat": {
"gitlens.gitExplorer.stashFileFormat": {
"type": "string",
"default": "${filePath}",
"description": "Specifies the format of a stashed file in the `Git Stashes` explorer\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
"description": "Specifies the format of a stashed file in the `GitLens` custom view\nAvailable tokens\n ${file} - file name\n ${filePath} - file name and path\n ${path} - file path"
},
"gitlens.statusBar.enabled": {
"type": "boolean",
@ -772,17 +786,17 @@
},
{
"command": "gitlens.diffWithNext",
"title": "Compare File with Next Commit",
"title": "Compare File with Next Revision",
"category": "GitLens"
},
{
"command": "gitlens.diffWithPrevious",
"title": "Compare File with Previous",
"title": "Compare File with Previous Revision",
"category": "GitLens"
},
{
"command": "gitlens.diffLineWithPrevious",
"title": "Compare Line Commit with Previous",
"title": "Compare Line Revision with Previous",
"category": "GitLens"
},
{
@ -792,12 +806,12 @@
},
{
"command": "gitlens.diffWithWorking",
"title": "Compare File with Working Tree",
"title": "Compare File with Working Revision",
"category": "GitLens"
},
{
"command": "gitlens.diffLineWithWorking",
"title": "Compare Line Commit with Working Tree",
"title": "Compare Line Revision with Working",
"category": "GitLens"
},
{
@ -864,7 +878,11 @@
{
"command": "gitlens.showCommitSearch",
"title": "Search Commits",
"category": "GitLens"
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-search.svg",
"light": "images/light/icon-search.svg"
}
},
{
"command": "gitlens.showFileHistory",
@ -985,66 +1003,56 @@
}
},
{
"command": "gitlens.fileHistoryExplorer.refresh",
"title": "Refresh",
"command": "gitlens.gitExplorer.switchToHistoryView",
"title": "Switch to History View",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-refresh.svg",
"light": "images/light/icon-refresh.svg"
"dark": "images/dark/icon-history.svg",
"light": "images/light/icon-history.svg"
}
},
{
"command": "gitlens.fileHistoryExplorer.openChanges",
"title": "Open Changes",
"category": "GitLens"
"command": "gitlens.gitExplorer.switchToRepositoryView",
"title": "Switch to Repository View",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-repo.svg",
"light": "images/light/icon-repo.svg"
}
},
{
"command": "gitlens.fileHistoryExplorer.openFile",
"title": "Open File",
"command": "gitlens.gitExplorer.openChanges",
"title": "Open Changes",
"category": "GitLens"
},
{
"command": "gitlens.fileHistoryExplorer.openFileRevision",
"title": "Open File Revision",
"command": "gitlens.gitExplorer.openChangesWithWorking",
"title": "Open Changes with Working Tree",
"category": "GitLens"
},
{
"command": "gitlens.fileHistoryExplorer.openFileInRemote",
"title": "Open File in Remote",
"command": "gitlens.gitExplorer.openFile",
"title": "Open File",
"category": "GitLens"
},
{
"command": "gitlens.fileHistoryExplorer.openFileRevisionInRemote",
"title": "Open File Revision in Remote",
"command": "gitlens.gitExplorer.openFileRevision",
"title": "Open Revision",
"category": "GitLens"
},
{
"command": "gitlens.stashExplorer.refresh",
"title": "Refresh",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-refresh.svg",
"light": "images/light/icon-refresh.svg"
}
},
{
"command": "gitlens.stashExplorer.openChanges",
"title": "Open Changes",
"command": "gitlens.gitExplorer.openFileRevisionInRemote",
"title": "Open Revision in Remote",
"category": "GitLens"
},
{
"command": "gitlens.stashExplorer.openFile",
"title": "Open File",
"command": "gitlens.gitExplorer.openChangedFiles",
"title": "Open Files",
"category": "GitLens"
},
{
"command": "gitlens.stashExplorer.openStashedFile",
"title": "Open Stashed File",
"category": "GitLens"
},
{
"command": "gitlens.stashExplorer.openFileInRemote",
"title": "Open File in Remote",
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"title": "Open Revisions",
"category": "GitLens"
}
],
@ -1203,47 +1211,39 @@
"when": "false"
},
{
"command": "gitlens.fileHistoryExplorer.refresh",
"when": "false"
},
{
"command": "gitlens.fileHistoryExplorer.openChanges",
"when": "false"
"command": "gitlens.gitExplorer.switchToHistoryView",
"when": "gitlens:gitExplorer:view == repository"
},
{
"command": "gitlens.fileHistoryExplorer.openFile",
"when": "false"
"command": "gitlens.gitExplorer.switchToRepositoryView",
"when": "gitlens:gitExplorer:view == history"
},
{
"command": "gitlens.fileHistoryExplorer.openFileRevision",
"command": "gitlens.gitExplorer.openChanges",
"when": "false"
},
{
"command": "gitlens.fileHistoryExplorer.openFileInRemote",
"command": "gitlens.gitExplorer.openChangesWithWorking",
"when": "false"
},
{
"command": "gitlens.fileHistoryExplorer.openFileRevisionInRemote",
"command": "gitlens.gitExplorer.openFile",
"when": "false"
},
{
"command": "gitlens.stashExplorer.refresh",
"command": "gitlens.gitExplorer.openFileRevision",
"when": "false"
},
{
"command": "gitlens.stashExplorer.openChanges",
"command": "gitlens.gitExplorer.openFileRevisionInRemote",
"when": "false"
},
{
"command": "gitlens.stashExplorer.openFile",
"command": "gitlens.gitExplorer.openChangedFiles",
"when": "false"
},
{
"command": "gitlens.stashExplorer.openStashedFile",
"when": "false"
},
{
"command": "gitlens.stashExplorer.openFileInRemote",
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"when": "false"
}
],
@ -1432,116 +1432,156 @@
],
"view/title": [
{
"command": "gitlens.gitExplorer.refresh",
"command": "gitlens.showCommitSearch",
"when": "gitlens:enabled && view == gitlens.gitExplorer",
"group": "navigation"
"group": "navigation@1"
},
{
"command": "gitlens.fileHistoryExplorer.refresh",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer",
"group": "navigation"
"command": "gitlens.gitExplorer.switchToHistoryView",
"when": "gitlens:enabled && view == gitlens.gitExplorer && gitlens:gitExplorer:view == repository",
"group": "navigation@2"
},
{
"command": "gitlens.stashSave",
"when": "gitlens:enabled && view == gitlens.stashExplorer",
"group": "navigation@1"
"command": "gitlens.gitExplorer.switchToRepositoryView",
"when": "gitlens:enabled && view == gitlens.gitExplorer && gitlens:gitExplorer:view == history",
"group": "navigation@3"
},
{
"command": "gitlens.stashExplorer.refresh",
"when": "gitlens:enabled && view == gitlens.stashExplorer",
"group": "navigation@2"
"command": "gitlens.gitExplorer.refresh",
"when": "gitlens:enabled && view == gitlens.gitExplorer",
"group": "navigation@4"
}
],
"view/item/context": [
{
"command": "gitlens.openCommitInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == commit",
"command": "gitlens.openBranchInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:branch-history",
"group": "1_gitlens@1"
},
{
"command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == commit-file",
"command": "gitlens.openCommitInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "1_gitlens@1"
},
{
"command": "gitlens.diffWithPrevious",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == commit-file",
"command": "gitlens.copyShaToClipboard",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "2_gitlens@1"
},
{
"command": "gitlens.diffWithWorking",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == commit-file",
"command": "gitlens.copyMessageToClipboard",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "2_gitlens@2"
},
{
"command": "gitlens.fileHistoryExplorer.openChanges",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"command": "gitlens.gitExplorer.openChangedFiles",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "3_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "3_gitlens@2"
},
{
"command": "gitlens.showQuickCommitDetails",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit",
"group": "4_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChanges",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "1_gitlens@1"
},
{
"command": "gitlens.diffWithWorking",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"command": "gitlens.gitExplorer.openChangesWithWorking",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "1_gitlens@2"
},
{
"command": "gitlens.fileHistoryExplorer.openFile",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"command": "gitlens.gitExplorer.openFile",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "2_gitlens@1"
},
{
"command": "gitlens.fileHistoryExplorer.openFileRevision",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"command": "gitlens.gitExplorer.openFileRevision",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "2_gitlens@2"
},
{
"command": "gitlens.fileHistoryExplorer.openFileInRemote",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"group": "2_gitlens@3"
"command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "3_gitlens@1"
},
{
"command": "gitlens.fileHistoryExplorer.openFileRevisionInRemote",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"group": "2_gitlens@4"
"command": "gitlens.gitExplorer.openFileRevisionInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "3_gitlens@2"
},
{
"command": "gitlens.showQuickCommitDetails",
"when": "gitlens:enabled && view == gitlens.fileHistoryExplorer && viewItem == commit-file",
"group": "3_gitlens@1"
"command": "gitlens.showQuickFileHistory",
"when": "gitlens:isTracked && view == gitlens.gitExplorer && viewItem == gitlens:commit-file && gitlens:gitExplorer:view == repository",
"group": "4_gitlens@1"
},
{
"command": "gitlens.showQuickCommitFileDetails",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:commit-file",
"group": "4_gitlens@2"
},
{
"command": "gitlens.stashApply",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == stash-commit",
"group": "3_gitlens@1"
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "1_gitlens@1"
},
{
"command": "gitlens.stashDelete",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == stash-commit",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "1_gitlens@2"
},
{
"command": "gitlens.copyMessageToClipboard",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "2_gitlens@1"
},
{
"command": "gitlens.gitExplorer.openChangedFiles",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "3_gitlens@1"
},
{
"command": "gitlens.stashExplorer.openChanges",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == commit-file",
"command": "gitlens.gitExplorer.openChangedFileRevisions",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash",
"group": "3_gitlens@2"
},
{
"command": "gitlens.gitExplorer.openChanges",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "1_gitlens@1"
},
{
"command": "gitlens.stashExplorer.openFile",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == commit-file",
"command": "gitlens.gitExplorer.openChangesWithWorking",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "1_gitlens@2"
},
{
"command": "gitlens.stashExplorer.openStashedFile",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == commit-file",
"group": "1_gitlens@3"
"command": "gitlens.gitExplorer.openFile",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "2_gitlens@1"
},
{
"command": "gitlens.stashExplorer.openFileInRemote",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == commit-file",
"group": "1_gitlens@4"
"command": "gitlens.gitExplorer.openFileRevision",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "2_gitlens@2"
},
{
"command": "gitlens.diffWithWorking",
"when": "gitlens:enabled && view == gitlens.stashExplorer && viewItem == commit-file",
"group": "2_gitlens@2"
"command": "gitlens.openFileInRemote",
"when": "gitlens:enabled && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "3_gitlens@1"
},
{
"command": "gitlens.showQuickFileHistory",
"when": "gitlens:isTracked && view == gitlens.gitExplorer && viewItem == gitlens:stash-file",
"group": "4_gitlens@1"
}
]
},
@ -1640,13 +1680,8 @@
"views": {
"explorer": [
{
"id": "gitlens.fileHistoryExplorer",
"name": "Git File History",
"when": "gitlens:enabled && config.gitlens.insiders"
},
{
"id": "gitlens.stashExplorer",
"name": "Git Stashes",
"id": "gitlens.gitExplorer",
"name": "GitLens",
"when": "gitlens:enabled"
}
]

+ 13
- 0
src/commands/common.ts Ver fichero

@ -1,6 +1,7 @@
'use strict';
import { commands, Disposable, SourceControlResourceGroup, SourceControlResourceState, TextDocumentShowOptions, TextEditor, TextEditorEdit, Uri, window, workspace } from 'vscode';
import { ExplorerNode } from '../views/explorerNodes';
import { GitBranch, GitCommit } from '../gitService';
import { Logger } from '../logger';
import { Telemetry } from '../telemetry';
@ -125,6 +126,18 @@ export interface CommandViewContext extends CommandBaseContext {
node: ExplorerNode;
}
export function isCommandViewContextWithBranch(context: CommandContext): context is CommandViewContext & { node: (ExplorerNode & { branch: GitBranch }) } {
return context.type === 'view' && (context.node as any).branch && (context.node as any).branch instanceof GitBranch;
}
interface ICommandViewContextWithCommit<T extends GitCommit> extends CommandViewContext {
node: (ExplorerNode & { commit: T });
}
export function isCommandViewContextWithCommit<T extends GitCommit>(context: CommandContext): context is ICommandViewContextWithCommit<T> {
return context.type === 'view' && (context.node as any).commit && (context.node as any).commit instanceof GitCommit;
}
export type CommandContext = CommandScmGroupsContext | CommandScmStatesContext | CommandUnknownContext | CommandUriContext | CommandViewContext;
function isScmResourceGroup(group: any): group is SourceControlResourceGroup {

+ 12
- 2
src/commands/copyMessageToClipboard.ts Ver fichero

@ -1,7 +1,7 @@
'use strict';
import { Iterables } from '../system';
import { TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { copy } from 'copy-paste';
@ -17,6 +17,16 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
super(Commands.CopyMessageToClipboard);
}
protected async preExecute(context: CommandContext, args: CopyMessageToClipboardCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithCommit(context)) {
args = { ...args };
args.sha = context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: CopyMessageToClipboardCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor);
@ -64,7 +74,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand {
// Get the full commit message -- since blame only returns the summary
const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, args.sha);
if (!commit) return undefined;
if (commit === undefined) return undefined;
args.message = commit.message;
}

+ 12
- 2
src/commands/copyShaToClipboard.ts Ver fichero

@ -1,7 +1,7 @@
'use strict';
import { Iterables } from '../system';
import { TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { copy } from 'copy-paste';
@ -16,6 +16,16 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
super(Commands.CopyShaToClipboard);
}
protected async preExecute(context: CommandContext, args: CopyShaToClipboardCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithCommit(context)) {
args = { ...args };
args.sha = context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: CopyShaToClipboardCommandArgs = {}): Promise<any> {
uri = getCommandUri(uri, editor);
@ -45,7 +55,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand {
try {
const blame = await this.git.getBlameForLine(gitUri, blameline);
if (!blame) return undefined;
if (blame === undefined) return undefined;
args.sha = blame.commit.sha;
}

+ 10
- 4
src/commands/diffWithPrevious.ts Ver fichero

@ -2,7 +2,7 @@
import { Iterables } from '../system';
import { commands, Range, TextDocumentShowOptions, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { BuiltInCommands, GlyphChars } from '../constants';
import { BuiltInCommands, FakeSha, GlyphChars } from '../constants';
import { DiffWithWorkingCommandArgs } from './diffWithWorking';
import { GitCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
@ -14,6 +14,10 @@ export interface DiffWithPreviousCommandArgs {
line?: number;
range?: Range;
showOptions?: TextDocumentShowOptions;
allowMissingPrevious?: boolean;
leftTitlePrefix?: string;
rightTitlePrefix?: string;
}
export class DiffWithPreviousCommand extends ActiveEditorCommand {
@ -51,12 +55,12 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
}
}
if (args.commit.previousSha === undefined) return Messages.showCommitHasNoPreviousCommitWarningMessage(args.commit);
if (args.commit.previousSha === undefined && !args.allowMissingPrevious) return Messages.showCommitHasNoPreviousCommitWarningMessage(args.commit);
try {
const [rhs, lhs] = await Promise.all([
this.git.getVersionedFile(args.commit.repoPath, args.commit.uri.fsPath, args.commit.sha),
this.git.getVersionedFile(args.commit.repoPath, args.commit.previousUri.fsPath, args.commit.previousSha)
this.git.getVersionedFile(args.commit.repoPath, args.commit.previousUri.fsPath, args.commit.previousSha === undefined ? FakeSha : args.commit.previousSha)
]);
if (args.line !== undefined && args.line !== 0) {
@ -69,7 +73,9 @@ export class DiffWithPreviousCommand extends ActiveEditorCommand {
await commands.executeCommand(BuiltInCommands.Diff,
Uri.file(lhs),
Uri.file(rhs),
`${path.basename(args.commit.previousUri.fsPath)} (${args.commit.previousShortSha}) ${GlyphChars.ArrowLeftRight} ${path.basename(args.commit.uri.fsPath)} (${args.commit.shortSha})`,
args.commit.previousShortSha === undefined
? `${path.basename(args.commit.uri.fsPath)} (${args.rightTitlePrefix || ''}${args.commit.shortSha})`
: `${path.basename(args.commit.previousUri.fsPath)} (${args.leftTitlePrefix || ''}${args.commit.previousShortSha}) ${GlyphChars.ArrowLeftRight} ${path.basename(args.commit.uri.fsPath)} (${args.rightTitlePrefix || ''}${args.commit.shortSha})`,
args.showOptions);
}
catch (ex) {

+ 11
- 1
src/commands/openBranchInRemote.ts Ver fichero

@ -1,7 +1,7 @@
'use strict';
import { Arrays } from '../system';
import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithBranch } from './common';
import { GlyphChars } from '../constants';
import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
@ -18,6 +18,16 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand {
super(Commands.OpenBranchInRemote);
}
protected async preExecute(context: CommandContext, args: OpenBranchInRemoteCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithBranch(context)) {
args = { ...args };
args.branch = context.node.branch.name;
return this.execute(context.editor, context.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: OpenBranchInRemoteCommandArgs = {}) {
uri = getCommandUri(uri, editor);

+ 2
- 3
src/commands/openCommitInRemote.ts Ver fichero

@ -1,12 +1,11 @@
'use strict';
import { Arrays } from '../system';
import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri } from './common';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GitBlameCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { Messages } from '../messages';
import { OpenInRemoteCommandArgs } from './openInRemote';
import { CommitNode } from '../views/explorerNodes';
export interface OpenCommitInRemoteCommandArgs {
sha?: string;
@ -19,7 +18,7 @@ export class OpenCommitInRemoteCommand extends ActiveEditorCommand {
}
protected async preExecute(context: CommandContext, args: OpenCommitInRemoteCommandArgs = {}): Promise<any> {
if (context.type === 'view' && context.node instanceof CommitNode) {
if (isCommandViewContextWithCommit(context)) {
args = { ...args };
args.sha = context.node.commit.sha;
return this.execute(context.editor, context.node.commit.uri, args);

+ 11
- 1
src/commands/openFileInRemote.ts Ver fichero

@ -1,7 +1,7 @@
'use strict';
import { Arrays } from '../system';
import { commands, Range, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
import { ActiveEditorCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { OpenInRemoteCommandArgs } from './openInRemote';
@ -16,6 +16,16 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand {
super(Commands.OpenFileInRemote);
}
protected async preExecute(context: CommandContext, args: OpenFileInRemoteCommandArgs = {}): Promise<any> {
if (isCommandViewContextWithCommit(context)) {
args = { ...args };
args.range = false;
return this.execute(context.editor, context.node.commit.uri, args);
}
return this.execute(context.editor, context.uri, args);
}
async execute(editor?: TextEditor, uri?: Uri, args: OpenFileInRemoteCommandArgs = { range: true }) {
uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined;

+ 21
- 14
src/commands/openInRemote.ts Ver fichero

@ -28,6 +28,7 @@ export class OpenInRemoteCommand extends ActiveEditorCommand {
try {
if (args.remotes.length === 1) {
this.ensureRemoteBranchName(args);
const command = new OpenRemoteCommandQuickPickItem(args.remotes[0], args.resource);
return command.execute();
}
@ -35,16 +36,7 @@ export class OpenInRemoteCommand extends ActiveEditorCommand {
let placeHolder = '';
switch (args.resource.type) {
case 'branch':
// Check to see if the remote is in the branch
const index = args.resource.branch.indexOf('/');
if (index >= 0) {
const remoteName = args.resource.branch.substring(0, index);
const remote = args.remotes.find(r => r.name === remoteName);
if (remote !== undefined) {
args.resource.branch = args.resource.branch.substring(index + 1);
args.remotes = [remote];
}
}
this.ensureRemoteBranchName(args);
placeHolder = `open ${args.resource.branch} branch in${GlyphChars.Ellipsis}`;
break;
@ -54,6 +46,10 @@ export class OpenInRemoteCommand extends ActiveEditorCommand {
break;
case 'file':
placeHolder = `open ${args.resource.fileName} in${GlyphChars.Ellipsis}`;
break;
case 'revision':
if (args.resource.commit !== undefined && args.resource.commit instanceof GitLogCommit) {
if (args.resource.commit.status === 'D') {
args.resource.sha = args.resource.commit.previousSha;
@ -71,10 +67,6 @@ export class OpenInRemoteCommand extends ActiveEditorCommand {
placeHolder = `open ${args.resource.fileName}${shaSuffix} in${GlyphChars.Ellipsis}`;
}
break;
case 'working-file':
placeHolder = `open ${args.resource.fileName} in${GlyphChars.Ellipsis}`;
break;
}
if (args.remotes.length === 1) {
@ -93,4 +85,19 @@ export class OpenInRemoteCommand extends ActiveEditorCommand {
return window.showErrorMessage(`Unable to open in remote provider. See output channel for more details`);
}
}
private ensureRemoteBranchName(args: OpenInRemoteCommandArgs) {
if (args.remotes === undefined || args.resource === undefined || args.resource.type !== 'branch') return;
// Check to see if the remote is in the branch
const index = args.resource.branch.indexOf('/');
if (index >= 0) {
const remoteName = args.resource.branch.substring(0, index);
const remote = args.remotes.find(r => r.name === remoteName);
if (remote !== undefined) {
args.resource.branch = args.resource.branch.substring(index + 1);
args.remotes = [remote];
}
}
}
}

+ 0
- 7
src/commands/showCommitSearch.ts Ver fichero

@ -8,7 +8,6 @@ import { Logger } from '../logger';
import { Messages } from '../messages';
import { CommandQuickPickItem, CommitsQuickPick } from '../quickPicks';
import { ShowQuickCommitDetailsCommandArgs } from './showQuickCommitDetails';
import { paste } from 'copy-paste';
const searchByRegex = /^([@:#])/;
const searchByMap = new Map<string, GitRepoSearchBy>([
@ -49,12 +48,6 @@ export class ShowCommitSearchCommand extends ActiveEditorCachedCommand {
args.search = `#${blameLine.commit.shortSha}`;
}
}
if (!args.search) {
args.search = await new Promise<string>((resolve, reject) => {
paste((err: Error, content: string) => resolve(err ? '' : content));
});
}
}
}
catch (ex) {

+ 6
- 6
src/commands/showFileHistory.ts Ver fichero

@ -2,7 +2,7 @@
import { commands, Position, Range, TextEditor, TextEditorEdit, Uri, window } from 'vscode';
import { Commands, EditorCommand, getCommandUri } from './common';
import { BuiltInCommands } from '../constants';
import { GitExplorer } from '../views/gitExplorer';
// import { GitExplorer } from '../views/gitExplorer';
import { GitService, GitUri } from '../gitService';
import { Messages } from '../messages';
import { Logger } from '../logger';
@ -15,7 +15,7 @@ export interface ShowFileHistoryCommandArgs {
export class ShowFileHistoryCommand extends EditorCommand {
constructor(private git: GitService, private explorer?: GitExplorer) {
constructor(private git: GitService) {
super(Commands.ShowFileHistory);
}
@ -33,10 +33,10 @@ export class ShowFileHistoryCommand extends EditorCommand {
const gitUri = await GitUri.fromUri(uri, this.git);
try {
if (this.explorer !== undefined) {
this.explorer.addHistory(gitUri);
return undefined;
}
// if (this.explorer !== undefined) {
// this.explorer.addHistory(gitUri);
// return undefined;
// }
const locations = await this.git.getLogLocations(gitUri, args.sha, args.line);
if (locations === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to show file history');

+ 2
- 3
src/commands/showQuickCommitDetails.ts Ver fichero

@ -1,9 +1,8 @@
'use strict';
import { Strings } from '../system';
import { commands, TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCachedCommand, CommandContext, Commands, getCommandUri } from './common';
import { ActiveEditorCachedCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GlyphChars } from '../constants';
import { CommitNode } from '../views/explorerNodes';
import { GitCommit, GitLog, GitLogCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
import { CommandQuickPickItem, CommitDetailsQuickPick, CommitWithFileStatusQuickPickItem } from '../quickPicks';
@ -27,7 +26,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand {
protected async preExecute(context: CommandContext, ...args: any[]): Promise<any> {
if (context.type === 'view') {
if (context.node instanceof CommitNode) {
if (isCommandViewContextWithCommit(context)) {
args = [{ sha: context.node.uri.sha, commit: context.node.commit }];
}
else {

+ 13
- 1
src/commands/showQuickCommitFileDetails.ts Ver fichero

@ -1,7 +1,7 @@
'use strict';
import { Strings } from '../system';
import { TextEditor, Uri, window } from 'vscode';
import { ActiveEditorCachedCommand, Commands, getCommandUri } from './common';
import { ActiveEditorCachedCommand, CommandContext, Commands, getCommandUri, isCommandViewContextWithCommit } from './common';
import { GlyphChars } from '../constants';
import { GitCommit, GitLog, GitLogCommit, GitService, GitUri } from '../gitService';
import { Logger } from '../logger';
@ -24,6 +24,18 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand
super(Commands.ShowQuickCommitFileDetails);
}
protected async preExecute(context: CommandContext, ...args: any[]): Promise<any> {
if (context.type === 'view') {
if (isCommandViewContextWithCommit(context)) {
args = [{ sha: context.node.uri.sha, commit: context.node.commit }];
}
else {
args = [{ sha: context.node.uri.sha }];
}
}
return this.execute(context.editor, context.uri, ...args);
}
async execute(editor?: TextEditor, uri?: Uri, args: ShowQuickCommitFileDetailsCommandArgs = {}) {
uri = getCommandUri(uri, editor);
if (uri === undefined) return undefined;

+ 5
- 10
src/commands/stashApply.ts Ver fichero

@ -1,13 +1,11 @@
'use strict';
import { Strings } from '../system';
import { MessageItem, window } from 'vscode';
import { GitService, GitStashCommit } from '../gitService';
import { Command, CommandContext, Commands } from './common';
import { Command, CommandContext, Commands, isCommandViewContextWithCommit } from './common';
import { GlyphChars } from '../constants';
import { CommitQuickPickItem, StashListQuickPick } from '../quickPicks';
import { GitService, GitStashCommit } from '../gitService';
import { Logger } from '../logger';
import { CommandQuickPickItem } from '../quickPicks';
import { StashCommitNode } from '../views/stashCommitNode';
import { CommandQuickPickItem, CommitQuickPickItem, StashListQuickPick } from '../quickPicks';
export interface StashApplyCommandArgs {
confirm?: boolean;
@ -24,12 +22,9 @@ export class StashApplyCommand extends Command {
}
protected async preExecute(context: CommandContext, args: StashApplyCommandArgs = { confirm: true, deleteAfter: false }) {
if (context.type === 'view' && context.node instanceof StashCommitNode) {
if (isCommandViewContextWithCommit<GitStashCommit>(context)) {
args = { ...args };
const stash = context.node.commit;
args.stashItem = { stashName: stash.stashName, message: stash.message };
args.stashItem = { stashName: context.node.commit.stashName, message: context.node.commit.message };
return this.execute(args);
}

+ 4
- 8
src/commands/stashDelete.ts Ver fichero

@ -1,11 +1,10 @@
'use strict';
import { MessageItem, window } from 'vscode';
import { Command, CommandContext, Commands } from './common';
import { Command, CommandContext, Commands, isCommandViewContextWithCommit } from './common';
import { GlyphChars } from '../constants';
import { GitService } from '../gitService';
import { GitService, GitStashCommit } from '../gitService';
import { Logger } from '../logger';
import { CommandQuickPickItem } from '../quickPicks';
import { StashCommitNode } from '../views/stashCommitNode';
export interface StashDeleteCommandArgs {
confirm?: boolean;
@ -21,12 +20,9 @@ export class StashDeleteCommand extends Command {
}
protected async preExecute(context: CommandContext, args: StashDeleteCommandArgs = { confirm: true }) {
if (context.type === 'view' && context.node instanceof StashCommitNode) {
if (isCommandViewContextWithCommit<GitStashCommit>(context)) {
args = { ...args };
const stash = context.node.commit;
args.stashItem = { stashName: stash.stashName, message: stash.message };
args.stashItem = { stashName: context.node.commit.stashName, message: context.node.commit.message };
return this.execute(args);
}

+ 2
- 10
src/configuration.ts Ver fichero

@ -2,6 +2,7 @@
import { FileAnnotationType } from './annotations/annotationController';
import { Commands } from './commands';
import { LineAnnotationType } from './currentLineController';
import { GitExplorerView } from './views/gitExplorer';
import { OutputLevel } from './logger';
export { ExtensionKey } from './constants';
@ -296,19 +297,10 @@ export interface IConfig {
defaultDateFormat: string | null;
fileHistoryExplorer: {
commitFormat: string;
// commitFileFormat: string;
// dateFormat: string | null;
};
gitExplorer: {
view: GitExplorerView;
commitFormat: string;
commitFileFormat: string;
// dateFormat: string | null;
};
stashExplorer: {
stashFormat: string;
stashFileFormat: string;
// dateFormat: string | null;

+ 10
- 4
src/constants.ts Ver fichero

@ -8,6 +8,8 @@ export const QualifiedExtensionId = `eamodio.${ExtensionId}`;
export const ApplicationInsightsKey = 'a9c302f8-6483-4d01-b92c-c159c799c679';
export const FakeSha = 'ffffffffffffffffffffffffffffffffffffffff';
export type BuiltInCommands = 'cursorMove' |
'editor.action.showReferences' |
'editor.action.toggleRenderWhitespace' |
@ -40,23 +42,25 @@ export const BuiltInCommands = {
};
export type CommandContext =
'gitlens:annotationStatus' |
'gitlens:canToggleCodeLens' |
'gitlens:enabled' |
'gitlens:hasRemotes' |
'gitlens:gitExplorer:view' |
'gitlens:isBlameable' |
'gitlens:isRepository' |
'gitlens:isTracked' |
'gitlens:key' |
'gitlens:annotationStatus';
'gitlens:key';
export const CommandContext = {
AnnotationStatus: 'gitlens:annotationStatus' as CommandContext,
CanToggleCodeLens: 'gitlens:canToggleCodeLens' as CommandContext,
Enabled: 'gitlens:enabled' as CommandContext,
GitExplorerView: 'gitlens:gitExplorer:view' as CommandContext,
HasRemotes: 'gitlens:hasRemotes' as CommandContext,
IsBlameable: 'gitlens:isBlameable' as CommandContext,
IsRepository: 'gitlens:isRepository' as CommandContext,
IsTracked: 'gitlens:isTracked' as CommandContext,
Key: 'gitlens:key' as CommandContext,
AnnotationStatus: 'gitlens:annotationStatus' as CommandContext
Key: 'gitlens:key' as CommandContext
};
export function setCommandContext(key: CommandContext | string, value: any) {
@ -77,6 +81,7 @@ export type GlyphChars = '\u21a9' |
'\u2194' |
'\u21e8' |
'\u2191' |
'\u2713' |
'\u2014' |
'\u2022' |
'\u2026' |
@ -90,6 +95,7 @@ export const GlyphChars = {
ArrowLeftRight: '\u2194' as GlyphChars,
ArrowRightHollow: '\u21e8' as GlyphChars,
ArrowUp: '\u2191' as GlyphChars,
Check: '\u2713' as GlyphChars,
Dash: '\u2014' as GlyphChars,
Dot: '\u2022' as GlyphChars,
Ellipsis: '\u2026' as GlyphChars,

+ 2
- 2
src/currentLineController.ts Ver fichero

@ -476,11 +476,11 @@ export class CurrentLineController extends Disposable {
break;
case StatusBarCommand.DiffWithPrevious:
this._statusBarItem.command = Commands.DiffLineWithPrevious;
this._statusBarItem.tooltip = 'Compare Line Commit with Previous';
this._statusBarItem.tooltip = 'Compare Line Revision with Previous';
break;
case StatusBarCommand.DiffWithWorking:
this._statusBarItem.command = Commands.DiffLineWithWorking;
this._statusBarItem.tooltip = 'Compare Line Commit with Working Tree';
this._statusBarItem.tooltip = 'Compare Line Revision with Working';
break;
case StatusBarCommand.ToggleCodeLens:
this._statusBarItem.tooltip = 'Toggle Git CodeLens';

+ 2
- 8
src/extension.ts Ver fichero

@ -20,9 +20,7 @@ import { ApplicationInsightsKey, CommandContext, ExtensionKey, QualifiedExtensio
import { CodeLensController } from './codeLensController';
import { CurrentLineController, LineAnnotationType } from './currentLineController';
import { GitContentProvider } from './gitContentProvider';
// import { GitExplorer } from './views/gitExplorer';
import { FileHistoryExplorer } from './views/fileHistoryExplorer';
import { StashExplorer } from './views/stashExplorer';
import { GitExplorer } from './views/gitExplorer';
import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider';
import { GitContextTracker, GitService } from './gitService';
import { Keyboard } from './keyboard';
@ -94,11 +92,7 @@ export async function activate(context: ExtensionContext) {
context.subscriptions.push(new Keyboard());
// const explorer = new GitExplorer(context, git);
// context.subscriptions.push(window.registerTreeDataProvider('gitlens.gitExplorer', explorer));
context.subscriptions.push(window.registerTreeDataProvider('gitlens.fileHistoryExplorer', new FileHistoryExplorer(context, git)));
context.subscriptions.push(window.registerTreeDataProvider('gitlens.stashExplorer', new StashExplorer(context, git)));
context.subscriptions.push(window.registerTreeDataProvider('gitlens.gitExplorer', new GitExplorer(context, git)));
context.subscriptions.push(commands.registerTextEditorCommand('gitlens.computingFileAnnotations', () => { }));

+ 3
- 1
src/git/git.ts Ver fichero

@ -31,7 +31,9 @@ const GitWarnings = [
/Not a git repository/,
/is outside repository/,
/no such path/,
/does not have any commits/
/does not have any commits/,
/Path \'.*?\' does not exist in/,
/Path \'.*?\' exists on disk, but not in/
];
async function gitCommand(options: { cwd: string, encoding?: string }, ...args: any[]) {

+ 11
- 15
src/git/remotes/provider.ts Ver fichero

@ -3,12 +3,13 @@ import { commands, Range, Uri } from 'vscode';
import { BuiltInCommands } from '../../constants';
import { GitLogCommit } from '../../gitService';
export type RemoteResourceType = 'branch' | 'commit' | 'file' | 'repo' | 'working-file';
export type RemoteResource = { type: 'branch', branch: string } |
export type RemoteResourceType = 'branch' | 'commit' | 'file' | 'repo' | 'revision';
export type RemoteResource =
{ type: 'branch', branch: string } |
{ type: 'commit', sha: string } |
{ type: 'file', branch?: string, commit?: GitLogCommit, fileName: string, range?: Range, sha?: string } |
{ type: 'file', branch?: string, fileName: string, range?: Range } |
{ type: 'repo' } |
{ type: 'working-file', branch?: string, fileName: string, range?: Range };
{ type: 'revision', branch?: string, commit?: GitLogCommit, fileName: string, range?: Range, sha?: string };
export function getNameFromRemoteResource(resource: RemoteResource) {
switch (resource.type) {
@ -16,7 +17,7 @@ export function getNameFromRemoteResource(resource: RemoteResource) {
case 'commit': return 'Commit';
case 'file': return 'File';
case 'repo': return 'Repository';
case 'working-file': return 'Working File';
case 'revision': return 'Revision';
default: return '';
}
}
@ -43,16 +44,11 @@ export abstract class RemoteProvider {
open(resource: RemoteResource): Promise<{} | undefined> {
switch (resource.type) {
case 'branch':
return this.openBranch(resource.branch);
case 'commit':
return this.openCommit(resource.sha);
case 'file':
return this.openFile(resource.fileName, resource.branch, resource.sha, resource.range);
case 'repo':
return this.openRepo();
case 'working-file':
return this.openFile(resource.fileName, resource.branch, undefined, resource.range);
case 'branch': return this.openBranch(resource.branch);
case 'commit': return this.openCommit(resource.sha);
case 'file': return this.openFile(resource.fileName, resource.branch, undefined, resource.range);
case 'repo': return this.openRepo();
case 'revision': return this.openFile(resource.fileName, resource.branch, resource.sha, resource.range);
}
}

+ 4
- 4
src/gitContentProvider.ts Ver fichero

@ -1,5 +1,5 @@
'use strict';
import { ExtensionContext, TextDocumentContentProvider, Uri, window } from 'vscode';
import { CancellationToken, ExtensionContext, TextDocumentContentProvider, Uri, window } from 'vscode';
import { DocumentSchemes } from './constants';
import { GitService } from './gitService';
import { Logger } from './logger';
@ -11,7 +11,7 @@ export class GitContentProvider implements TextDocumentContentProvider {
constructor(context: ExtensionContext, private git: GitService) { }
async provideTextDocumentContent(uri: Uri): Promise<string> {
async provideTextDocumentContent(uri: Uri, token: CancellationToken): Promise<string | undefined> {
const data = GitService.fromGitContentUri(uri);
const fileName = data.originalFileName || data.fileName;
try {
@ -23,8 +23,8 @@ export class GitContentProvider implements TextDocumentContentProvider {
}
catch (ex) {
Logger.error(ex, 'GitContentProvider', 'getVersionedFileText');
await window.showErrorMessage(`Unable to show Git revision ${data.sha.substring(0, 8)} of '${path.relative(data.repoPath, fileName)}'`);
return '';
window.showErrorMessage(`Unable to show Git revision ${data.sha.substring(0, 8)} of '${path.relative(data.repoPath, fileName)}'`);
return undefined;
}
}
}

+ 5
- 6
src/gitRevisionCodeLensProvider.ts Ver fichero

@ -32,13 +32,12 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider {
const lenses: CodeLens[] = [];
const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true, previous: true });
if (!commit) return lenses;
lenses.push(new GitDiffWithWorkingCodeLens(this.git, commit.uri.fsPath, commit, new Range(0, 0, 0, 1)));
if (commit === undefined) return lenses;
if (commit.previousSha) {
lenses.push(new GitDiffWithPreviousCodeLens(this.git, commit.previousUri.fsPath, commit, new Range(0, 1, 0, 2)));
lenses.push(new GitDiffWithPreviousCodeLens(this.git, commit.previousUri.fsPath, commit, new Range(0, 0, 0, 1)));
}
lenses.push(new GitDiffWithWorkingCodeLens(this.git, commit.uri.fsPath, commit, new Range(0, 1, 0, 2)));
return lenses;
}
@ -51,7 +50,7 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider {
_resolveDiffWithWorkingTreeCodeLens(lens: GitDiffWithWorkingCodeLens, token: CancellationToken): Thenable<CodeLens> {
lens.command = {
title: `Compare ${lens.commit.shortSha} with Working Tree`,
title: `Compare Revision (${lens.commit.shortSha}) with Working`,
command: Commands.DiffWithWorking,
arguments: [
Uri.file(lens.fileName),
@ -66,7 +65,7 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider {
_resolveGitDiffWithPreviousCodeLens(lens: GitDiffWithPreviousCodeLens, token: CancellationToken): Thenable<CodeLens> {
lens.command = {
title: `Compare ${lens.commit.shortSha} with Previous ${lens.commit.previousShortSha}`,
title: `Compare Revision (${lens.commit.shortSha}) with Previous (${lens.commit.previousShortSha})`,
command: Commands.DiffWithPrevious,
arguments: [
Uri.file(lens.fileName),

+ 18
- 15
src/quickPicks/commitDetails.ts Ver fichero

@ -69,28 +69,31 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI
export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem {
constructor(commit: GitLogCommit, item?: QuickPickItem) {
const uris = commit.fileStatuses.map(s => (s.status === 'D')
? GitService.toGitContentUri(commit.previousSha!, commit.previousShortSha!, s.fileName, commit.repoPath, s.originalFileName)
: GitService.toGitContentUri(commit.sha, commit.shortSha, s.fileName, commit.repoPath, s.originalFileName));
constructor(commit: GitLogCommit, versioned: boolean = false, item?: QuickPickItem) {
const repoPath = commit.repoPath;
const uris = commit.fileStatuses
.filter(s => s.status !== 'D')
.map(s => GitUri.fromFileStatus(s, repoPath));
super(uris, item || {
label: `$(file-symlink-file) Open Changed Files`,
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}`
// detail: `Opens all of the changed files in $(git-commit) ${commit.shortSha}`
description: ''
// detail: `Opens all of the changed file in the working tree`
});
}
}
export class OpenCommitWorkingTreeFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem {
export class OpenCommitFileRevisionsCommandQuickPickItem extends OpenFilesCommandQuickPickItem {
constructor(commit: GitLogCommit, item?: QuickPickItem) {
const uris = commit.fileStatuses
.filter(s => s.status !== 'D')
.map(s => GitService.toGitContentUri(commit.sha, commit.shortSha, s.fileName, commit.repoPath, s.originalFileName));
constructor(commit: GitLogCommit, versioned: boolean = false, item?: QuickPickItem) {
const repoPath = commit.repoPath;
const uris = commit.fileStatuses.filter(_ => _.status !== 'D').map(_ => GitUri.fromFileStatus(_, repoPath));
super(uris, item || {
label: `$(file-symlink-file) Open Changed Working Files`,
description: ''
// detail: `Opens all of the changed file in the working tree`
label: `$(file-symlink-file) Open Changed Revisions`,
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}`
// detail: `Opens all of the changed files in $(git-commit) ${commit.shortSha}`
});
}
}
@ -196,8 +199,8 @@ export class CommitDetailsQuickPick {
} as ShowQuickCommitDetailsCommandArgs
]));
items.push(new OpenCommitFilesCommandQuickPickItem(commit));
items.push(new OpenCommitWorkingTreeFilesCommandQuickPickItem(commit));
items.push(new OpenCommitFilesCommandQuickPickItem(commit));
items.push(new OpenCommitFileRevisionsCommandQuickPickItem(commit));
if (goBackCommand) {
items.splice(0, 0, goBackCommand);

+ 24
- 24
src/quickPicks/commitFileDetails.ts Ver fichero

@ -13,6 +13,17 @@ import * as path from 'path';
export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem {
constructor(commit: GitLogCommit, item?: QuickPickItem) {
const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName));
super(uri, item || {
label: `$(file-symlink-file) Open File`,
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)}`
});
}
}
export class OpenCommitFileRevisionCommandQuickPickItem extends OpenFileCommandQuickPickItem {
constructor(commit: GitLogCommit, item?: QuickPickItem) {
let description: string;
let uri: Uri;
if (commit.status === 'D') {
@ -24,23 +35,12 @@ export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPick
description = `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)} in ${GlyphChars.Space}$(git-commit) ${commit.shortSha}`;
}
super(uri, item || {
label: `$(file-symlink-file) Open File`,
label: `$(file-symlink-file) Open Revision`,
description: description
});
}
}
export class OpenCommitWorkingTreeFileCommandQuickPickItem extends OpenFileCommandQuickPickItem {
constructor(commit: GitLogCommit, item?: QuickPickItem) {
const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName));
super(uri, item || {
label: `$(file-symlink-file) Open Working File`,
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} ${path.basename(commit.fileName)}`
});
}
}
export class CommitFileDetailsQuickPick {
static async show(git: GitService, commit: GitLogCommit, uri: Uri, goBackCommand?: CommandQuickPickItem, currentCommand?: CommandQuickPickItem, fileLog?: GitLog): Promise<CommandQuickPickItem | undefined> {
@ -74,7 +74,7 @@ export class CommitFileDetailsQuickPick {
if (commit.previousSha) {
items.push(new CommandQuickPickItem({
label: `$(git-compare) Compare File with Previous`,
label: `$(git-compare) Compare File with Previous Revision`,
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.previousShortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(git-commit) ${commit.shortSha}`
}, Commands.DiffWithPrevious, [
commit.uri,
@ -87,7 +87,7 @@ export class CommitFileDetailsQuickPick {
if (commit.workingFileName) {
items.push(new CommandQuickPickItem({
label: `$(git-compare) Compare File with Working Tree`,
label: `$(git-compare) Compare File with Working Revision`,
description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(git-commit) ${commit.shortSha} ${GlyphChars.Space} $(git-compare) ${GlyphChars.Space} $(file-text) ${workingName}`
}, Commands.DiffWithWorking, [
Uri.file(path.resolve(commit.repoPath, commit.workingFileName)),
@ -120,28 +120,28 @@ export class CommitFileDetailsQuickPick {
]));
}
items.push(new OpenCommitFileCommandQuickPickItem(commit));
if (commit.workingFileName && commit.status !== 'D') {
items.push(new OpenCommitWorkingTreeFileCommandQuickPickItem(commit));
items.push(new OpenCommitFileCommandQuickPickItem(commit));
}
items.push(new OpenCommitFileRevisionCommandQuickPickItem(commit));
const remotes = Arrays.uniqueBy(await git.getRemotes(commit.repoPath), _ => _.url, _ => !!_.provider);
if (remotes.length) {
if (!stash) {
items.push(new OpenRemotesCommandQuickPickItem(remotes, {
type: 'file',
fileName: commit.fileName,
commit
} as RemoteResource, currentCommand));
}
if (commit.workingFileName && commit.status !== 'D') {
const branch = await git.getBranch(commit.repoPath || git.repoPath) as GitBranch;
items.push(new OpenRemotesCommandQuickPickItem(remotes, {
type: 'working-file',
type: 'file',
fileName: commit.workingFileName,
branch: branch.name
} as RemoteResource, currentCommand));
}
if (!stash) {
items.push(new OpenRemotesCommandQuickPickItem(remotes, {
type: 'revision',
fileName: commit.fileName,
commit
} as RemoteResource, currentCommand));
}
}
if (commit.workingFileName) {

+ 1
- 1
src/quickPicks/fileHistory.ts Ver fichero

@ -139,7 +139,7 @@ export class FileHistoryQuickPick {
const remotes = Arrays.uniqueBy(await git.getRemotes(uri.repoPath!), _ => _.url, _ => !!_.provider);
if (remotes.length) {
items.splice(index++, 0, new OpenRemotesCommandQuickPickItem(remotes, {
type: 'file',
type: 'revision',
branch: branch!.name,
fileName: uri.getRelativePath(),
sha: uri.sha

+ 8
- 8
src/quickPicks/remotes.ts Ver fichero

@ -44,6 +44,14 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem {
break;
case 'file':
description = `$(file-text) ${path.basename(resource.fileName)}`;
break;
case 'repo':
description = `$(repo) Repository`;
break;
case 'revision':
if (resource.commit !== undefined && resource.commit instanceof GitLogCommit) {
if (resource.commit.status === 'D') {
resource.sha = resource.commit.previousSha;
@ -59,14 +67,6 @@ export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem {
description = `$(file-text) ${path.basename(resource.fileName)}${shortFileSha ? ` in ${GlyphChars.Space}$(git-commit) ${shortFileSha}` : ''}`;
}
break;
case 'repo':
description = `$(repo) Repository`;
break;
case 'working-file':
description = `$(file-text) ${path.basename(resource.fileName)}`;
break;
}
const remote = remotes[0];

+ 16
- 7
src/views/branchHistoryNode.ts Ver fichero

@ -4,26 +4,35 @@ import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { CommitNode } from './commitNode';
import { GlyphChars } from '../constants';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitBranch, GitService, GitUri } from '../gitService';
import { GitBranch, GitRemote, GitService, GitUri } from '../gitService';
export class BranchHistoryNode extends ExplorerNode {
readonly resourceType: ResourceType = 'branch-history';
readonly resourceType: ResourceType = 'gitlens:branch-history';
constructor(public readonly branch: GitBranch, uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
constructor(public readonly branch: GitBranch, private readonly remote: GitRemote | undefined, uri: GitUri, private readonly template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<CommitNode[]> {
async getChildren(): Promise<ExplorerNode[]> {
const log = await this.git.getLogForRepo(this.uri.repoPath!, this.branch.name);
if (log === undefined) return [];
return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.template, this.context, this.git))];
}
getTreeItem(): TreeItem {
const item = new TreeItem(`${this.branch.name}${this.branch.current ? ` ${GlyphChars.Dash} current` : ''}`, TreeItemCollapsibleState.Collapsed);
async getTreeItem(): Promise<TreeItem> {
const name = this.remote !== undefined
? this.branch.name.substring(this.remote.name.length + 1)
: this.branch.name;
const item = new TreeItem(`${name}${this.branch!.current ? ` ${GlyphChars.Space} ${GlyphChars.Check}` : ''}`, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-branch.svg'),
light: this.context.asAbsolutePath('images/light/icon-branch.svg')
};
return item;
}
}

+ 11
- 4
src/views/branchesNode.ts Ver fichero

@ -7,22 +7,29 @@ import { GitService, GitUri } from '../gitService';
export class BranchesNode extends ExplorerNode {
readonly resourceType: ResourceType = 'branches';
readonly resourceType: ResourceType = 'gitlens:branches';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<BranchHistoryNode[]> {
async getChildren(): Promise<ExplorerNode[]> {
const branches = await this.git.getBranches(this.uri.repoPath!);
if (branches === undefined) return [];
return [...Iterables.filterMap(branches.sort(_ => _.current ? 0 : 1), b => b.remote ? undefined : new BranchHistoryNode(b, this.uri, this.context, this.git))];
branches.sort((a, b) => (a.current ? -1 : 1) - (b.current ? -1 : 1) || a.name.localeCompare(b.name));
return [...Iterables.filterMap(branches, b => b.remote ? undefined : new BranchHistoryNode(b, undefined, this.uri, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
}
getTreeItem(): TreeItem {
const item = new TreeItem(`Branches`, TreeItemCollapsibleState.Collapsed);
const item = new TreeItem(`Branches`, TreeItemCollapsibleState.Expanded);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-branch.svg'),
light: this.context.asAbsolutePath('images/light/icon-branch.svg')
};
return item;
}
}

+ 17
- 5
src/views/commitFileNode.ts Ver fichero

@ -7,9 +7,9 @@ import * as path from 'path';
export class CommitFileNode extends ExplorerNode {
readonly resourceType: ResourceType = 'commit-file';
readonly resourceType: ResourceType = 'gitlens:commit-file';
constructor(public readonly status: IGitStatusFile, public commit: GitCommit, private template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
constructor(public readonly status: IGitStatusFile, public commit: GitCommit, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(new GitUri(Uri.file(path.resolve(commit.repoPath, status.fileName)), { repoPath: commit.repoPath, fileName: status.fileName, sha: commit.sha }));
}
@ -25,7 +25,7 @@ export class CommitFileNode extends ExplorerNode {
}
}
const item = new TreeItem(StatusFileFormatter.fromTemplate(this.template, this.status), TreeItemCollapsibleState.None);
const item = new TreeItem(StatusFileFormatter.fromTemplate(this.git.config.gitExplorer.commitFileFormat, this.status), TreeItemCollapsibleState.None);
item.contextValue = this.resourceType;
const icon = getGitStatusIcon(this.status.status);
@ -40,8 +40,18 @@ export class CommitFileNode extends ExplorerNode {
}
getCommand(): Command | undefined {
let allowMissingPrevious = false;
let prefix = undefined;
if (this.status.status === 'A') {
allowMissingPrevious = true;
prefix = 'added in ';
}
else if (this.status.status === 'D') {
prefix = 'deleted in ';
}
return {
title: 'Compare File with Previous',
title: 'Compare File with Previous Revision',
command: Commands.DiffWithPrevious,
arguments: [
GitUri.fromFileStatus(this.status, this.commit.repoPath),
@ -51,7 +61,9 @@ export class CommitFileNode extends ExplorerNode {
showOptions: {
preserveFocus: true,
preview: true
}
},
allowMissingPrevious: allowMissingPrevious,
rightTitlePrefix: prefix
} as DiffWithPreviousCommandArgs
]
};

+ 21
- 7
src/views/commitNode.ts Ver fichero

@ -4,13 +4,13 @@ import { Command, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'v
import { Commands, DiffWithPreviousCommandArgs } from '../commands';
import { CommitFileNode } from './commitFileNode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { CommitFormatter, GitCommit, GitService, GitUri } from '../gitService';
import { CommitFormatter, GitLogCommit, GitService, GitUri } from '../gitService';
export class CommitNode extends ExplorerNode {
readonly resourceType: ResourceType = 'commit';
readonly resourceType: ResourceType = 'gitlens:commit';
constructor(public readonly commit: GitCommit, private template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
constructor(public readonly commit: GitLogCommit, private readonly template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(new GitUri(commit.uri, commit));
}
@ -23,7 +23,7 @@ export class CommitNode extends ExplorerNode {
const commit = Iterables.first(log.commits.values());
if (commit === undefined) return [];
return [...Iterables.map(commit.fileStatuses, s => new CommitFileNode(s, commit, this.git.config.gitExplorer.commitFileFormat, this.context, this.git))];
return [...Iterables.map(commit.fileStatuses, s => new CommitFileNode(s, commit, this.context, this.git))];
}
getTreeItem(): TreeItem {
@ -31,7 +31,8 @@ export class CommitNode extends ExplorerNode {
if (this.commit.type === 'file') {
item.collapsibleState = TreeItemCollapsibleState.None;
item.command = this.getCommand();
item.contextValue = 'commit-file';
const resourceType: ResourceType = 'gitlens:commit-file';
item.contextValue = resourceType;
}
else {
item.collapsibleState = TreeItemCollapsibleState.Collapsed;
@ -47,8 +48,19 @@ export class CommitNode extends ExplorerNode {
}
getCommand(): Command | undefined {
let allowMissingPrevious = false;
let prefix = undefined;
const status = this.commit.fileStatuses[0];
if (status.status === 'A') {
allowMissingPrevious = true;
prefix = 'added in ';
}
else if (status.status === 'D') {
prefix = 'deleted in ';
}
return {
title: 'Compare File with Previous',
title: 'Compare File with Previous Revision',
command: Commands.DiffWithPrevious,
arguments: [
new GitUri(this.uri, this.commit),
@ -58,7 +70,9 @@ export class CommitNode extends ExplorerNode {
showOptions: {
preserveFocus: true,
preview: true
}
},
allowMissingPrevious: allowMissingPrevious,
rightTitlePrefix: prefix
} as DiffWithPreviousCommandArgs
]
};

+ 20
- 5
src/views/explorerNode.ts Ver fichero

@ -2,7 +2,22 @@
import { Command, Event, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GitUri } from '../gitService';
export declare type ResourceType = 'text' | 'status' | 'branches' | 'repository' | 'branch-history' | 'file-history' | 'stash-history' | 'commit' | 'stash-commit' | 'commit-file';
export declare type ResourceType =
'gitlens:branches' |
'gitlens:branch-history' |
'gitlens:commit' |
'gitlens:commit-file' |
'gitlens:file-history' |
'gitlens:history' |
'gitlens:message' |
'gitlens:remote' |
'gitlens:remotes' |
'gitlens:repository' |
'gitlens:stash' |
'gitlens:stash-file' |
'gitlens:stashes' |
'gitlens:status' |
'gitlens:status-upstream';
export abstract class ExplorerNode {
@ -22,11 +37,11 @@ export abstract class ExplorerNode {
refresh?(): void;
}
export class TextExplorerNode extends ExplorerNode {
export class MessageNode extends ExplorerNode {
readonly resourceType: ResourceType = 'text';
readonly resourceType: ResourceType = 'gitlens:message';
constructor(private text: string) {
constructor(private message: string) {
super(new GitUri());
}
@ -35,7 +50,7 @@ export class TextExplorerNode extends ExplorerNode {
}
getTreeItem(): TreeItem | Promise<TreeItem> {
const item = new TreeItem(this.text, TreeItemCollapsibleState.None);
const item = new TreeItem(this.message, TreeItemCollapsibleState.None);
item.contextValue = this.resourceType;
return item;
}

+ 7
- 2
src/views/explorerNodes.ts Ver fichero

@ -6,7 +6,12 @@ export * from './branchHistoryNode';
export * from './commitFileNode';
export * from './commitNode';
export * from './fileHistoryNode';
export * from './historyNode';
export * from './remoteNode';
export * from './remotesNode';
export * from './repositoryNode';
export * from './stashCommitNode';
export * from './stashFileNode';
export * from './stashNode';
export * from './statusNode';
export * from './stashesNode';
export * from './statusNode';
export * from './statusUpstreamNode';

+ 0
- 89
src/views/fileHistoryExplorer.ts Ver fichero

@ -1,89 +0,0 @@
'use strict';
// import { Arrays } from '../system';
import { commands, Event, EventEmitter, ExtensionContext, TextEditor, TreeDataProvider, TreeItem, Uri, window } from 'vscode';
import { Commands, DiffWithPreviousCommandArgs, openEditor, OpenFileInRemoteCommandArgs } from '../commands';
import { UriComparer } from '../comparers';
import { CommitNode, ExplorerNode, FileHistoryNode, TextExplorerNode } from './explorerNodes';
import { GitService, GitUri } from '../gitService';
export * from './explorerNodes';
export class FileHistoryExplorer implements TreeDataProvider<ExplorerNode> {
private _node?: ExplorerNode;
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
public get onDidChangeTreeData(): Event<ExplorerNode> {
return this._onDidChangeTreeData.event;
}
constructor(private context: ExtensionContext, private git: GitService) {
commands.registerCommand('gitlens.fileHistoryExplorer.refresh', this.refresh, this);
commands.registerCommand('gitlens.fileHistoryExplorer.openChanges', this.openChanges, this);
commands.registerCommand('gitlens.fileHistoryExplorer.openFile', this.openFile, this);
commands.registerCommand('gitlens.fileHistoryExplorer.openFileRevision', this.openFileRevision, this);
commands.registerCommand('gitlens.fileHistoryExplorer.openFileInRemote', this.openFileInRemote, this);
commands.registerCommand('gitlens.fileHistoryExplorer.openFileRevisionInRemote', this.openFileRevisionInRemote, this);
context.subscriptions.push(window.onDidChangeActiveTextEditor(this.onActiveEditorChanged, this));
this._node = this.getRootNode(window.activeTextEditor);
}
async getTreeItem(node: ExplorerNode): Promise<TreeItem> {
return node.getTreeItem();
}
async getChildren(node?: ExplorerNode): Promise<ExplorerNode[]> {
if (this._node === undefined) return [new TextExplorerNode('No active file')];
if (node === undefined) return this._node.getChildren();
return node.getChildren();
}
private getRootNode(editor: TextEditor | undefined): ExplorerNode | undefined {
if (window.visibleTextEditors.length === 0) return undefined;
if (editor === undefined) return this._node;
const uri = this.git.getGitUriForFile(editor.document.uri) || new GitUri(editor.document.uri, { repoPath: this.git.repoPath, fileName: editor.document.uri.fsPath });
if (UriComparer.equals(uri, this._node && this._node.uri)) return this._node;
return new FileHistoryNode(uri, this.context, this.git);
}
private onActiveEditorChanged(editor: TextEditor | undefined) {
const node = this.getRootNode(editor);
if (node === this._node) return;
this.refresh();
}
refresh(node?: ExplorerNode) {
this._node = node || this.getRootNode(window.activeTextEditor);
this._onDidChangeTreeData.fire();
}
private openChanges(node: CommitNode) {
const command = node.getCommand();
if (command === undefined || command.arguments === undefined) return;
const [uri, args] = command.arguments as [Uri, DiffWithPreviousCommandArgs];
args.showOptions!.preview = false;
return commands.executeCommand(command.command, uri, args);
}
private openFile(node: CommitNode) {
return openEditor(node.uri, { preserveFocus: true, preview: false });
}
private openFileRevision(node: CommitNode) {
return openEditor(GitService.toGitContentUri(node.uri), { preserveFocus: true, preview: false });
}
private async openFileInRemote(node: CommitNode) {
return commands.executeCommand(Commands.OpenFileInRemote, node.commit.uri, { range: false } as OpenFileInRemoteCommandArgs);
}
private async openFileRevisionInRemote(node: CommitNode) {
return commands.executeCommand(Commands.OpenFileInRemote, new GitUri(node.commit.uri, node.commit), { range: false } as OpenFileInRemoteCommandArgs);
}
}

+ 11
- 6
src/views/fileHistoryNode.ts Ver fichero

@ -2,13 +2,12 @@
import { Iterables } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { CommitNode } from './commitNode';
import { ExplorerNode, ResourceType, TextExplorerNode } from './explorerNode';
import { ExplorerNode, MessageNode, ResourceType } from './explorerNode';
import { GitService, GitUri } from '../gitService';
export class FileHistoryNode extends ExplorerNode {
static readonly rootType: ResourceType = 'file-history';
readonly resourceType: ResourceType = 'file-history';
readonly resourceType: ResourceType = 'gitlens:file-history';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
@ -16,14 +15,20 @@ export class FileHistoryNode extends ExplorerNode {
async getChildren(): Promise<ExplorerNode[]> {
const log = await this.git.getLogForFile(this.uri.repoPath, this.uri.fsPath, this.uri.sha);
if (log === undefined) return [new TextExplorerNode('No file history')];
if (log === undefined) return [new MessageNode('No file history')];
return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.git.config.fileHistoryExplorer.commitFormat, this.context, this.git))];
return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
}
getTreeItem(): TreeItem {
const item = new TreeItem(`History of ${this.uri.getFormattedPath()}`, TreeItemCollapsibleState.Expanded);
const item = new TreeItem(`${this.uri.getFormattedPath()}`, TreeItemCollapsibleState.Expanded);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-history.svg'),
light: this.context.asAbsolutePath('images/light/icon-history.svg')
};
return item;
}
}

+ 125
- 36
src/views/gitExplorer.ts Ver fichero

@ -1,73 +1,162 @@
'use strict';
// import { Functions } from '../system';
import { commands, Event, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem, Uri } from 'vscode';
import { Functions } from '../system';
import { commands, Event, EventEmitter, ExtensionContext, TextDocumentShowOptions, TextEditor, TreeDataProvider, TreeItem, Uri, window } from 'vscode';
import { Commands, DiffWithPreviousCommandArgs, DiffWithWorkingCommandArgs, openEditor, OpenFileInRemoteCommandArgs } from '../commands';
import { UriComparer } from '../comparers';
import { ExplorerNode, FileHistoryNode, RepositoryNode, ResourceType, StashNode } from './explorerNodes';
import { CommandContext, setCommandContext } from '../constants';
import { CommitFileNode, CommitNode, ExplorerNode, HistoryNode, MessageNode, RepositoryNode, StashNode } from './explorerNodes';
import { GitService, GitUri } from '../gitService';
export * from './explorerNodes';
export type GitExplorerView =
'history' |
'repository';
export const GitExplorerView = {
History: 'history' as GitExplorerView,
Repository: 'repository' as GitExplorerView
};
export interface OpenFileRevisionCommandArgs {
uri?: Uri;
showOptions?: TextDocumentShowOptions;
}
export class GitExplorer implements TreeDataProvider<ExplorerNode> {
// private _refreshDebounced: () => void;
private _root?: ExplorerNode;
private _view: GitExplorerView = GitExplorerView.Repository;
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
public get onDidChangeTreeData(): Event<ExplorerNode> {
return this._onDidChangeTreeData.event;
}
private _roots: ExplorerNode[] = [];
constructor(private readonly context: ExtensionContext, private readonly git: GitService) {
commands.registerCommand('gitlens.gitExplorer.switchToHistoryView', () => this.switchTo(GitExplorerView.History), this);
commands.registerCommand('gitlens.gitExplorer.switchToRepositoryView', () => this.switchTo(GitExplorerView.Repository), this);
commands.registerCommand('gitlens.gitExplorer.refresh', this.refresh, this);
commands.registerCommand('gitlens.gitExplorer.openChanges', this.openChanges, this);
commands.registerCommand('gitlens.gitExplorer.openChangesWithWorking', this.openChangesWithWorking, this);
commands.registerCommand('gitlens.gitExplorer.openFile', this.openFile, this);
commands.registerCommand('gitlens.gitExplorer.openFileRevision', this.openFileRevision, this);
commands.registerCommand('gitlens.gitExplorer.openFileRevisionInRemote', this.openFileRevisionInRemote, this);
commands.registerCommand('gitlens.gitExplorer.openChangedFiles', this.openChangedFiles, this);
commands.registerCommand('gitlens.gitExplorer.openChangedFileRevisions', this.openChangedFileRevisions, this);
const fn = Functions.debounce(this.onActiveEditorChanged, 500);
context.subscriptions.push(window.onDidChangeActiveTextEditor(fn, this));
this._view = this.git.config.gitExplorer.view;
setCommandContext(CommandContext.GitExplorerView, this._view);
this._root = this.getRootNode();
}
constructor(private context: ExtensionContext, private git: GitService) {
commands.registerCommand('gitlens.gitExplorer.refresh', () => this.refresh());
async getTreeItem(node: ExplorerNode): Promise<TreeItem> {
return node.getTreeItem();
}
async getChildren(node?: ExplorerNode): Promise<ExplorerNode[]> {
if (this._root === undefined) {
if (this._view === GitExplorerView.History) return [new MessageNode('No active file; no history to show')];
return [];
}
// this._refreshDebounced = Functions.debounce(this.refresh.bind(this), 250);
if (node === undefined) return this._root.getChildren();
return node.getChildren();
}
// const editor = window.activeTextEditor;
private getRootNode(editor?: TextEditor): ExplorerNode | undefined {
const uri = new GitUri(Uri.file(this.git.repoPath), { repoPath: this.git.repoPath, fileName: this.git.repoPath });
// const uri = (editor !== undefined && editor.document !== undefined)
// ? new GitUri(editor.document.uri, { repoPath: git.repoPath, fileName: editor.document.uri.fsPath })
// : new GitUri(Uri.file(git.repoPath), { repoPath: git.repoPath, fileName: git.repoPath });
switch (this._view) {
case GitExplorerView.History: return this.getHistoryNode(editor || window.activeTextEditor);
case GitExplorerView.Repository: return new RepositoryNode(uri, this.context, this.git);
}
const uri = new GitUri(Uri.file(git.repoPath), { repoPath: git.repoPath, fileName: git.repoPath });
this._roots.push(new RepositoryNode(uri, context, git));
return undefined;
}
async getTreeItem(node: ExplorerNode): Promise<TreeItem> {
// if (node.onDidChangeTreeData !== undefined) {
// node.onDidChangeTreeData(() => setTimeout(this._refreshDebounced, 1));
// }
return node.getTreeItem();
private getHistoryNode(editor: TextEditor | undefined): ExplorerNode | undefined {
if (window.visibleTextEditors.length === 0) return undefined;
if (editor === undefined) return this._root;
const uri = this.git.getGitUriForFile(editor.document.uri) || new GitUri(editor.document.uri, { repoPath: this.git.repoPath, fileName: editor.document.uri.fsPath });
if (UriComparer.equals(uri, this._root && this._root.uri)) return this._root;
return new HistoryNode(uri, this.context, this.git);
}
async getChildren(node?: ExplorerNode): Promise<ExplorerNode[]> {
if (this._roots.length === 0) return [];
if (node === undefined) return this._roots;
private onActiveEditorChanged(editor: TextEditor | undefined) {
if (this._view !== GitExplorerView.History) return;
const root = this.getRootNode(editor);
if (root === this._root) return;
return node.getChildren();
this.refresh(root);
}
addHistory(uri: GitUri) {
this._add(uri, FileHistoryNode);
refresh(root?: ExplorerNode) {
this._root = root || this.getRootNode();
this._onDidChangeTreeData.fire();
}
switchTo(view: GitExplorerView) {
if (this._view === view) return;
this._view = view;
setCommandContext(CommandContext.GitExplorerView, this._view);
this._root = undefined;
this.refresh();
}
private openChanges(node: CommitNode | StashNode) {
const command = node.getCommand();
if (command === undefined || command.arguments === undefined) return;
const [uri, args] = command.arguments as [Uri, DiffWithPreviousCommandArgs];
args.showOptions!.preview = false;
return commands.executeCommand(command.command, uri, args);
}
addStash(uri: GitUri) {
this._add(uri, StashNode);
private openChangesWithWorking(node: CommitNode | StashNode) {
const args: DiffWithWorkingCommandArgs = {
commit: node.commit,
showOptions: {
preserveFocus: true,
preview: false
}
};
return commands.executeCommand(Commands.DiffWithWorking, new GitUri(node.commit.uri, node.commit), args);
}
private openFile(node: CommitNode | StashNode) {
return openEditor(node.uri, { preserveFocus: true, preview: false });
}
private openFileRevision(node: CommitNode | StashNode | CommitFileNode, options: OpenFileRevisionCommandArgs = { showOptions: { preserveFocus: true, preview: false } }) {
return openEditor(options.uri || GitService.toGitContentUri(node.uri), options.showOptions || { preserveFocus: true, preview: false });
}
private _add<T extends ExplorerNode>(uri: GitUri, type: { new (uri: GitUri, context: ExtensionContext, git: GitService): T, rootType: ResourceType }) {
if (!this._roots.some(_ => _.resourceType === type.rootType && UriComparer.equals(uri, _.uri))) {
this._roots.push(new type(uri, this.context, this.git));
private async openChangedFiles(node: CommitNode | StashNode, options: TextDocumentShowOptions = { preserveFocus: false, preview: false }) {
const repoPath = node.commit.repoPath;
const uris = node.commit.fileStatuses.filter(s => s.status !== 'D').map(s => GitUri.fromFileStatus(s, repoPath));
for (const uri of uris) {
await openEditor(uri, options);
}
this.refresh();
}
clear() {
this._roots = [];
this.refresh();
private async openChangedFileRevisions(node: CommitNode | StashNode, options: TextDocumentShowOptions = { preserveFocus: false, preview: false }) {
const uris = node.commit.fileStatuses
.filter(s => s.status !== 'D')
.map(s => GitService.toGitContentUri(node.commit.sha, node.commit.shortSha, s.fileName, node.commit.repoPath, s.originalFileName));
for (const uri of uris) {
await openEditor(uri, options);
}
}
refresh() {
this._onDidChangeTreeData.fire();
private async openFileRevisionInRemote(node: CommitNode | StashNode) {
return commands.executeCommand(Commands.OpenFileInRemote, new GitUri(node.commit.uri, node.commit), { range: false } as OpenFileInRemoteCommandArgs);
}
}

+ 30
- 0
src/views/historyNode.ts Ver fichero

@ -0,0 +1,30 @@
'use strict';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { FileHistoryNode } from './fileHistoryNode';
import { GitService, GitUri } from '../gitService';
export class HistoryNode extends ExplorerNode {
readonly resourceType: ResourceType = 'gitlens:history';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<ExplorerNode[]> {
return [new FileHistoryNode(this.uri, this.context, this.git)];
}
getTreeItem(): TreeItem {
const item = new TreeItem(`${this.uri.getFormattedPath()}`, TreeItemCollapsibleState.Expanded);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-history.svg'),
light: this.context.asAbsolutePath('images/light/icon-history.svg')
};
return item;
}
}

+ 35
- 0
src/views/remoteNode.ts Ver fichero

@ -0,0 +1,35 @@
'use strict';
import { Iterables } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { BranchHistoryNode } from './branchHistoryNode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitRemote, GitService, GitUri } from '../gitService';
export class RemoteNode extends ExplorerNode {
readonly resourceType: ResourceType = 'gitlens:remote';
constructor(public readonly remote: GitRemote, uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<ExplorerNode[]> {
const branches = await this.git.getBranches(this.uri.repoPath!);
if (branches === undefined) return [];
branches.sort((a, b) => a.name.localeCompare(b.name));
return [...Iterables.filterMap(branches, b => !b.remote || !b.name.startsWith(this.remote.name) ? undefined : new BranchHistoryNode(b, this.remote, this.uri, this.git.config.gitExplorer.commitFormat, this.context, this.git))];
}
getTreeItem(): TreeItem {
const item = new TreeItem(this.remote.name, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
// item.iconPath = {
// dark: this.context.asAbsolutePath('images/dark/icon-remote.svg'),
// light: this.context.asAbsolutePath('images/light/icon-remote.svg')
// };
return item;
}
}

+ 35
- 0
src/views/remotesNode.ts Ver fichero

@ -0,0 +1,35 @@
'use strict';
import { Arrays, Iterables } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitService, GitUri } from '../gitService';
import { RemoteNode } from './remoteNode';
export class RemotesNode extends ExplorerNode {
readonly resourceType: ResourceType = 'gitlens:remotes';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<ExplorerNode[]> {
const remotes = Arrays.uniqueBy(await this.git.getRemotes(this.uri.repoPath!), r => r.url, r => !!r.provider);
if (remotes === undefined) return [];
remotes.sort((a, b) => a.name.localeCompare(b.name));
return [...Iterables.map(remotes, r => new RemoteNode(r, this.uri, this.context, this.git))];
}
getTreeItem(): TreeItem {
const item = new TreeItem(`Remotes`, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-remote.svg'),
light: this.context.asAbsolutePath('images/light/icon-remote.svg')
};
return item;
}
}

+ 8
- 5
src/views/repositoryNode.ts Ver fichero

@ -4,12 +4,13 @@ import { BranchesNode } from './branchesNode';
import { GlyphChars } from '../constants';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitService, GitUri } from '../gitService';
// import { StatusNode } from './statusNode';
import { RemotesNode } from './remotesNode';
import { StatusNode } from './statusNode';
import { StashesNode } from './stashesNode';
export class RepositoryNode extends ExplorerNode {
static readonly rootType: ResourceType = 'repository';
readonly resourceType: ResourceType = 'repository';
readonly resourceType: ResourceType = 'gitlens:repository';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
@ -17,8 +18,10 @@ export class RepositoryNode extends ExplorerNode {
async getChildren(): Promise<ExplorerNode[]> {
return [
// new StatusNode(this.uri, this.context, this.git),
new BranchesNode(this.uri, this.context, this.git)
new StatusNode(this.uri, this.context, this.git),
new BranchesNode(this.uri, this.context, this.git),
new RemotesNode(this.uri, this.context, this.git),
new StashesNode(this.uri, this.context, this.git)
];
}

+ 0
- 46
src/views/stashCommitNode.ts Ver fichero

@ -1,46 +0,0 @@
'use strict';
import { Event, EventEmitter, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { CommitFileNode } from './commitFileNode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { CommitFormatter, GitService, GitStashCommit, GitUri } from '../gitService';
export class StashCommitNode extends ExplorerNode {
readonly resourceType: ResourceType = 'stash-commit';
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
public get onDidChangeTreeData(): Event<ExplorerNode> {
return this._onDidChangeTreeData.event;
}
constructor(public readonly commit: GitStashCommit, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(new GitUri(commit.uri, commit));
}
async getChildren(): Promise<CommitFileNode[]> {
return Promise.resolve((this.commit as GitStashCommit).fileStatuses.map(_ => new CommitFileNode(_, this.commit, this.git.config.stashExplorer.stashFileFormat, this.context, this.git)));
}
getTreeItem(): TreeItem {
const label = CommitFormatter.fromTemplate(this.git.config.stashExplorer.stashFormat, this.commit, this.git.config.defaultDateFormat);
const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
// item.command = {
// title: 'Show Stash Details',
// command: Commands.ShowQuickCommitDetails,
// arguments: [
// new GitUri(commit.uri, commit),
// {
// commit: this.commit,
// sha: this.commit.sha
// } as ShowQuickCommitDetailsCommandArgs
// ]
// };
return item;
}
refresh() {
this._onDidChangeTreeData.fire();
}
}

+ 0
- 75
src/views/stashExplorer.ts Ver fichero

@ -1,75 +0,0 @@
'use strict';
// import { Functions } from '../system';
import { commands, Event, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem, Uri } from 'vscode';
import { Commands, DiffWithPreviousCommandArgs, openEditor, OpenFileInRemoteCommandArgs } from '../commands';
import { ExplorerNode, StashCommitNode, StashNode } from './explorerNodes';
import { GitService, GitUri } from '../gitService';
export * from './explorerNodes';
export class StashExplorer implements TreeDataProvider<ExplorerNode> {
private _node: ExplorerNode;
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
public get onDidChangeTreeData(): Event<ExplorerNode> {
return this._onDidChangeTreeData.event;
}
constructor(private context: ExtensionContext, private git: GitService) {
commands.registerCommand('gitlens.stashExplorer.refresh', this.refresh, this);
commands.registerCommand('gitlens.stashExplorer.openChanges', this.openChanges, this);
commands.registerCommand('gitlens.stashExplorer.openFile', this.openFile, this);
commands.registerCommand('gitlens.stashExplorer.openStashedFile', this.openStashedFile, this);
commands.registerCommand('gitlens.stashExplorer.openFileInRemote', this.openFileInRemote, this);
context.subscriptions.push(this.git.onDidChangeRepo(this.onRepoChanged, this));
this._node = this.getRootNode();
}
async getTreeItem(node: ExplorerNode): Promise<TreeItem> {
return node.getTreeItem();
}
async getChildren(node?: ExplorerNode): Promise<ExplorerNode[]> {
if (node === undefined) return this._node.getChildren();
return node.getChildren();
}
private getRootNode(): ExplorerNode {
const uri = new GitUri(Uri.file(this.git.repoPath), { repoPath: this.git.repoPath, fileName: this.git.repoPath });
return new StashNode(uri, this.context, this.git);
}
private onRepoChanged(reasons: ('stash' | 'unknown')[]) {
if (!reasons.includes('stash')) return;
this.refresh();
}
refresh() {
this._onDidChangeTreeData.fire();
}
private openChanges(node: StashCommitNode) {
const command = node.getCommand();
if (command === undefined || command.arguments === undefined) return;
const [uri, args] = command.arguments as [Uri, DiffWithPreviousCommandArgs];
args.showOptions!.preview = false;
return commands.executeCommand(command.command, uri, args);
}
private openFile(node: StashCommitNode) {
return openEditor(node.uri, { preserveFocus: true, preview: false });
}
private openStashedFile(node: StashCommitNode) {
return openEditor(GitService.toGitContentUri(node.uri), { preserveFocus: true, preview: false });
}
private openFileInRemote(node: StashCommitNode) {
return commands.executeCommand(Commands.OpenFileInRemote, node.commit.uri, { range: false } as OpenFileInRemoteCommandArgs);
}
}

+ 14
- 0
src/views/stashFileNode.ts Ver fichero

@ -0,0 +1,14 @@
'use strict';
import { ExtensionContext } from 'vscode';
import { ResourceType } from './explorerNode';
import { GitService, GitStashCommit, IGitStatusFile } from '../gitService';
import { CommitFileNode } from './commitFileNode';
export class StashFileNode extends CommitFileNode {
readonly resourceType: ResourceType = 'gitlens:stash-file';
constructor(readonly status: IGitStatusFile, readonly commit: GitStashCommit, readonly context: ExtensionContext, readonly git: GitService) {
super(status, commit, context, git);
}
}

+ 21
- 15
src/views/stashNode.ts Ver fichero

@ -1,29 +1,35 @@
'use strict';
import { Iterables } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ExplorerNode, ResourceType, TextExplorerNode } from './explorerNode';
import { GitService, GitUri } from '../gitService';
import { StashCommitNode } from './stashCommitNode';
import { Event, EventEmitter, ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { CommitFormatter, GitService, GitStashCommit, GitUri } from '../gitService';
import { StashFileNode } from './stashFileNode';
export class StashNode extends ExplorerNode {
static readonly rootType: ResourceType = 'stash-history';
readonly resourceType: ResourceType = 'stash-history';
readonly resourceType: ResourceType = 'gitlens:stash';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
private _onDidChangeTreeData = new EventEmitter<ExplorerNode>();
public get onDidChangeTreeData(): Event<ExplorerNode> {
return this._onDidChangeTreeData.event;
}
async getChildren(): Promise<ExplorerNode[]> {
const stash = await this.git.getStashList(this.uri.repoPath!);
if (stash === undefined) return [new TextExplorerNode('No stashed changes')];
constructor(public readonly commit: GitStashCommit, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(new GitUri(commit.uri, commit));
}
return [...Iterables.map(stash.commits.values(), c => new StashCommitNode(c, this.context, this.git))];
async getChildren(): Promise<ExplorerNode[]> {
return Promise.resolve((this.commit as GitStashCommit).fileStatuses.map(s => new StashFileNode(s, this.commit, this.context, this.git)));
}
getTreeItem(): TreeItem {
const item = new TreeItem(`Stashed Changes`, TreeItemCollapsibleState.Collapsed);
const label = CommitFormatter.fromTemplate(this.git.config.gitExplorer.stashFormat, this.commit, this.git.config.defaultDateFormat);
const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
return item;
}
refresh() {
this._onDidChangeTreeData.fire();
}
}

+ 34
- 0
src/views/stashesNode.ts Ver fichero

@ -0,0 +1,34 @@
'use strict';
import { Iterables } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ExplorerNode, MessageNode, ResourceType } from './explorerNode';
import { GitService, GitUri } from '../gitService';
import { StashNode } from './stashNode';
export class StashesNode extends ExplorerNode {
readonly resourceType: ResourceType = 'gitlens:stashes';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<ExplorerNode[]> {
const stash = await this.git.getStashList(this.uri.repoPath!);
if (stash === undefined) return [new MessageNode('No stashed changes')];
return [...Iterables.map(stash.commits.values(), c => new StashNode(c, this.context, this.git))];
}
getTreeItem(): TreeItem {
const item = new TreeItem(`Stashes`, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-stash.svg'),
light: this.context.asAbsolutePath('images/light/icon-stash.svg')
};
return item;
}
}

+ 37
- 11
src/views/statusNode.ts Ver fichero

@ -1,34 +1,60 @@
import { Strings } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { GlyphChars } from '../constants';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitService, GitUri } from '../gitService';
import { StatusUpstreamNode } from './statusUpstreamNode';
export class StatusNode extends ExplorerNode {
readonly resourceType: ResourceType = 'status';
readonly resourceType: ResourceType = 'gitlens:status';
constructor(uri: GitUri, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(uri);
}
async getChildren(): Promise<ExplorerNode[]> {
return [];
// const status = await this.git.getStatusForRepo(this.uri.repoPath!);
// if (status === undefined) return [];
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
if (status === undefined) return [];
const children = [];
if (status.state.behind) {
children.push(new StatusUpstreamNode(status, 'behind', this.git.config.gitExplorer.commitFormat, this.context, this.git));
}
if (status.state.ahead) {
children.push(new StatusUpstreamNode(status, 'ahead', this.git.config.gitExplorer.commitFormat, this.context, this.git));
}
// return [...Iterables.map(status.files, b => new CommitFile(b, this.uri, this.context, this.git))];
return children;
}
async getTreeItem(): Promise<TreeItem> {
const status = await this.git.getStatusForRepo(this.uri.repoPath!);
let suffix = '';
if (status !== undefined) {
suffix = ` ${GlyphChars.Dash} ${GlyphChars.ArrowUp} ${status.state.ahead} ${GlyphChars.ArrowDown} ${status.state.behind} ${Strings.pad(GlyphChars.Dot, 1, 1)} ${status.branch} ${GlyphChars.ArrowLeftRight} ${status.upstream}`;
if (status === undefined) return new TreeItem('No repo status');
let hasChildren = false;
let label = '';
if (status.upstream) {
if (!status.state.ahead && !status.state.behind) {
label = `${status.branch} is up-to-date with ${status.upstream}`;
}
else {
label = `${status.branch} is not up-to-date with ${status.upstream}`;
hasChildren = true;
}
}
else {
label = `${status.branch} is up-to-date`;
}
const item = new TreeItem(`Status${suffix}`, TreeItemCollapsibleState.Collapsed);
const item = new TreeItem(label, hasChildren ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath('images/dark/icon-repo.svg'),
light: this.context.asAbsolutePath('images/light/icon-repo.svg')
};
return item;
}
}

+ 53
- 0
src/views/statusUpstreamNode.ts Ver fichero

@ -0,0 +1,53 @@
'use strict';
import { Iterables } from '../system';
import { ExtensionContext, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitService, GitStatus, GitUri } from '../gitService';
import { CommitNode } from './commitNode';
export class StatusUpstreamNode extends ExplorerNode {
readonly resourceType: ResourceType = 'gitlens:status-upstream';
constructor(public readonly status: GitStatus, public readonly direction: 'ahead' | 'behind', private readonly template: string, protected readonly context: ExtensionContext, protected readonly git: GitService) {
super(new GitUri(Uri.file(status.repoPath), { repoPath: status.repoPath, fileName: status.repoPath }));
}
async getChildren(): Promise<ExplorerNode[]> {
const range = this.direction === 'ahead'
? `${this.status.upstream}..${this.status.branch}`
: `${this.status.branch}..${this.status.upstream}`;
let log = await this.git.getLogForRepo(this.uri.repoPath!, range);
if (log === undefined) return [];
if (this.direction !== 'ahead') return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.template, this.context, this.git))];
// Since the last commit when we are looking 'ahead' can have no previous (because of the range given) -- look it up
const commits = Array.from(log.commits.values());
const commit = commits[commits.length - 1];
if (commit.previousSha === undefined) {
log = await this.git.getLogForRepo(this.uri.repoPath!, commit.sha, 2);
if (log !== undefined) {
commits[commits.length - 1] = Iterables.first(log.commits.values());
}
}
return [...Iterables.map(commits, c => new CommitNode(c, this.template, this.context, this.git))];
}
async getTreeItem(): Promise<TreeItem> {
const label = this.direction === 'ahead'
? `${this.status.state.ahead} commit${this.status.state.ahead > 1 ? 's' : ''} ahead` // of ${this.status.upstream}`
: `${this.status.state.behind} commit${this.status.state.behind > 1 ? 's' : ''} behind`; // ${this.status.upstream}`;
const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed);
item.contextValue = this.resourceType;
item.iconPath = {
dark: this.context.asAbsolutePath(`images/dark/icon-${this.direction === 'ahead' ? 'upload' : 'download'}.svg`),
light: this.context.asAbsolutePath(`images/light/icon-${this.direction === 'ahead' ? 'upload' : 'download'}.svg`)
};
return item;
}
}

Cargando…
Cancelar
Guardar