webdiff 1.3.0b1__tar.gz → 1.4.0b2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/PKG-INFO +24 -9
  2. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/README.md +19 -3
  3. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/pyproject.toml +7 -5
  4. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/app.py +35 -10
  5. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/argparser.py +7 -3
  6. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/diff.py +6 -1
  7. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/dirdiff.py +5 -5
  8. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/github_fetcher.py +2 -2
  9. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/gitwebdiff.py +1 -0
  10. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/codediff.js/codediff.css +56 -0
  11. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/style.css +17 -7
  12. webdiff-1.4.0b2/webdiff/static/js/file_diff.js +3 -0
  13. webdiff-1.4.0b2/webdiff/toy.py +26 -0
  14. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/util.py +34 -6
  15. webdiff-1.3.0b1/webdiff/static/js/file_diff.js +0 -61
  16. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/LICENSE +0 -0
  17. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/__init__.py +0 -0
  18. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/githubdiff.py +0 -0
  19. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/gitwebshow.py +0 -0
  20. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/localfilediff.py +0 -0
  21. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/options.py +0 -0
  22. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/__init__.py +0 -0
  23. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/codediff.js/googlecode.css +0 -0
  24. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/Inconsolata/Inconsolata-Bold.ttf +0 -0
  25. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/Inconsolata/Inconsolata-Regular.ttf +0 -0
  26. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/Inconsolata/OFL.txt +0 -0
  27. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/googlecode.css +0 -0
  28. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/inconsolata.css +0 -0
  29. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/a11y-dark.css +0 -0
  30. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/a11y-light.css +0 -0
  31. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/agate.css +0 -0
  32. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/an-old-hope.css +0 -0
  33. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/androidstudio.css +0 -0
  34. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/arduino-light.css +0 -0
  35. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/arta.css +0 -0
  36. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/ascetic.css +0 -0
  37. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/atom-one-dark-reasonable.css +0 -0
  38. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/atom-one-dark.css +0 -0
  39. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/atom-one-light.css +0 -0
  40. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/3024.css +0 -0
  41. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/apathy.css +0 -0
  42. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/apprentice.css +0 -0
  43. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ashes.css +0 -0
  44. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-cave-light.css +0 -0
  45. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-cave.css +0 -0
  46. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-dune-light.css +0 -0
  47. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-dune.css +0 -0
  48. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-estuary-light.css +0 -0
  49. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-estuary.css +0 -0
  50. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-forest-light.css +0 -0
  51. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-forest.css +0 -0
  52. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-heath-light.css +0 -0
  53. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-heath.css +0 -0
  54. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-lakeside-light.css +0 -0
  55. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-lakeside.css +0 -0
  56. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-plateau-light.css +0 -0
  57. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-plateau.css +0 -0
  58. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-savanna-light.css +0 -0
  59. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-savanna.css +0 -0
  60. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-seaside-light.css +0 -0
  61. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-seaside.css +0 -0
  62. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-sulphurpool-light.css +0 -0
  63. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atelier-sulphurpool.css +0 -0
  64. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/atlas.css +0 -0
  65. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/bespin.css +0 -0
  66. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-bathory.css +0 -0
  67. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-burzum.css +0 -0
  68. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-dark-funeral.css +0 -0
  69. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-gorgoroth.css +0 -0
  70. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-immortal.css +0 -0
  71. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-khold.css +0 -0
  72. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-marduk.css +0 -0
  73. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-mayhem.css +0 -0
  74. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-nile.css +0 -0
  75. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal-venom.css +0 -0
  76. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/black-metal.css +0 -0
  77. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/brewer.css +0 -0
  78. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/bright.css +0 -0
  79. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/brogrammer.css +0 -0
  80. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/brush-trees-dark.css +0 -0
  81. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/brush-trees.css +0 -0
  82. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/chalk.css +0 -0
  83. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/circus.css +0 -0
  84. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/classic-dark.css +0 -0
  85. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/classic-light.css +0 -0
  86. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/codeschool.css +0 -0
  87. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/colors.css +0 -0
  88. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/cupcake.css +0 -0
  89. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/cupertino.css +0 -0
  90. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/danqing.css +0 -0
  91. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/darcula.css +0 -0
  92. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/dark-violet.css +0 -0
  93. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/darkmoss.css +0 -0
  94. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/darktooth.css +0 -0
  95. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/decaf.css +0 -0
  96. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/default-dark.css +0 -0
  97. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/default-light.css +0 -0
  98. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/dirtysea.css +0 -0
  99. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/dracula.css +0 -0
  100. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/edge-dark.css +0 -0
  101. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/edge-light.css +0 -0
  102. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/eighties.css +0 -0
  103. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/embers.css +0 -0
  104. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/equilibrium-dark.css +0 -0
  105. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/equilibrium-gray-dark.css +0 -0
  106. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/equilibrium-gray-light.css +0 -0
  107. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/equilibrium-light.css +0 -0
  108. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/espresso.css +0 -0
  109. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/eva-dim.css +0 -0
  110. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/eva.css +0 -0
  111. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/flat.css +0 -0
  112. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/framer.css +0 -0
  113. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/fruit-soda.css +0 -0
  114. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gigavolt.css +0 -0
  115. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/github.css +0 -0
  116. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/google-dark.css +0 -0
  117. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/google-light.css +0 -0
  118. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/grayscale-dark.css +0 -0
  119. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/grayscale-light.css +0 -0
  120. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/green-screen.css +0 -0
  121. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-dark-hard.css +0 -0
  122. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-dark-medium.css +0 -0
  123. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-dark-pale.css +0 -0
  124. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-dark-soft.css +0 -0
  125. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-light-hard.css +0 -0
  126. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-light-medium.css +0 -0
  127. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/gruvbox-light-soft.css +0 -0
  128. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/hardcore.css +0 -0
  129. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/harmonic16-dark.css +0 -0
  130. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/harmonic16-light.css +0 -0
  131. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/heetch-dark.css +0 -0
  132. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/heetch-light.css +0 -0
  133. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/helios.css +0 -0
  134. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/hopscotch.css +0 -0
  135. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/horizon-dark.css +0 -0
  136. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/horizon-light.css +0 -0
  137. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/humanoid-dark.css +0 -0
  138. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/humanoid-light.css +0 -0
  139. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ia-dark.css +0 -0
  140. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ia-light.css +0 -0
  141. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/icy-dark.css +0 -0
  142. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ir-black.css +0 -0
  143. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/isotope.css +0 -0
  144. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/kimber.css +0 -0
  145. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/london-tube.css +0 -0
  146. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/macintosh.css +0 -0
  147. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/marrakesh.css +0 -0
  148. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/materia.css +0 -0
  149. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/material-darker.css +0 -0
  150. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/material-lighter.css +0 -0
  151. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/material-palenight.css +0 -0
  152. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/material-vivid.css +0 -0
  153. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/material.css +0 -0
  154. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/mellow-purple.css +0 -0
  155. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/mexico-light.css +0 -0
  156. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/mocha.css +0 -0
  157. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/monokai.css +0 -0
  158. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/nebula.css +0 -0
  159. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/nord.css +0 -0
  160. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/nova.css +0 -0
  161. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ocean.css +0 -0
  162. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/oceanicnext.css +0 -0
  163. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/one-light.css +0 -0
  164. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/onedark.css +0 -0
  165. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/outrun-dark.css +0 -0
  166. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/papercolor-dark.css +0 -0
  167. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/papercolor-light.css +0 -0
  168. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/paraiso.css +0 -0
  169. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/pasque.css +0 -0
  170. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/phd.css +0 -0
  171. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/pico.css +0 -0
  172. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/pop.css +0 -0
  173. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/porple.css +0 -0
  174. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/qualia.css +0 -0
  175. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/railscasts.css +0 -0
  176. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/rebecca.css +0 -0
  177. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ros-pine-dawn.css +0 -0
  178. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ros-pine-moon.css +0 -0
  179. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/ros-pine.css +0 -0
  180. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/sagelight.css +0 -0
  181. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/sandcastle.css +0 -0
  182. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/seti-ui.css +0 -0
  183. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/shapeshifter.css +0 -0
  184. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/silk-dark.css +0 -0
  185. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/silk-light.css +0 -0
  186. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/snazzy.css +0 -0
  187. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/solar-flare-light.css +0 -0
  188. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/solar-flare.css +0 -0
  189. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/solarized-dark.css +0 -0
  190. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/solarized-light.css +0 -0
  191. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/spacemacs.css +0 -0
  192. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/summercamp.css +0 -0
  193. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/summerfruit-dark.css +0 -0
  194. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/summerfruit-light.css +0 -0
  195. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/synth-midnight-terminal-dark.css +0 -0
  196. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/synth-midnight-terminal-light.css +0 -0
  197. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/tango.css +0 -0
  198. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/tender.css +0 -0
  199. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/tomorrow-night.css +0 -0
  200. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/tomorrow.css +0 -0
  201. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/twilight.css +0 -0
  202. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/unikitty-dark.css +0 -0
  203. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/unikitty-light.css +0 -0
  204. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/vulcan.css +0 -0
  205. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-10-light.css +0 -0
  206. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-10.css +0 -0
  207. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-95-light.css +0 -0
  208. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-95.css +0 -0
  209. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-high-contrast-light.css +0 -0
  210. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-high-contrast.css +0 -0
  211. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-nt-light.css +0 -0
  212. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/windows-nt.css +0 -0
  213. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/woodland.css +0 -0
  214. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/xcode-dusk.css +0 -0
  215. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/base16/zenburn.css +0 -0
  216. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/brown-paper.css +0 -0
  217. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/brown-papersq.png +0 -0
  218. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/codepen-embed.css +0 -0
  219. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/color-brewer.css +0 -0
  220. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/dark.css +0 -0
  221. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/default.css +0 -0
  222. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/devibeans.css +0 -0
  223. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/docco.css +0 -0
  224. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/far.css +0 -0
  225. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/felipec.css +0 -0
  226. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/foundation.css +0 -0
  227. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/github-dark-dimmed.css +0 -0
  228. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/github-dark.css +0 -0
  229. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/github.css +0 -0
  230. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/gml.css +0 -0
  231. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/googlecode.css +0 -0
  232. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/gradient-dark.css +0 -0
  233. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/gradient-light.css +0 -0
  234. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/grayscale.css +0 -0
  235. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/hybrid.css +0 -0
  236. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/idea.css +0 -0
  237. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/intellij-light.css +0 -0
  238. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/ir-black.css +0 -0
  239. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/isbl-editor-dark.css +0 -0
  240. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/isbl-editor-light.css +0 -0
  241. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/kimbie-dark.css +0 -0
  242. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/kimbie-light.css +0 -0
  243. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/lightfair.css +0 -0
  244. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/lioshi.css +0 -0
  245. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/magula.css +0 -0
  246. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/mono-blue.css +0 -0
  247. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/monokai-sublime.css +0 -0
  248. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/monokai.css +0 -0
  249. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/night-owl.css +0 -0
  250. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/nnfx-dark.css +0 -0
  251. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/nnfx-light.css +0 -0
  252. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/nord.css +0 -0
  253. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/obsidian.css +0 -0
  254. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/panda-syntax-dark.css +0 -0
  255. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/panda-syntax-light.css +0 -0
  256. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/paraiso-dark.css +0 -0
  257. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/paraiso-light.css +0 -0
  258. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/pojoaque.css +0 -0
  259. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/pojoaque.jpg +0 -0
  260. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/purebasic.css +0 -0
  261. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/qtcreator-dark.css +0 -0
  262. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/qtcreator-light.css +0 -0
  263. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/rainbow.css +0 -0
  264. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/routeros.css +0 -0
  265. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/school-book.css +0 -0
  266. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/shades-of-purple.css +0 -0
  267. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/srcery.css +0 -0
  268. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/stackoverflow-dark.css +0 -0
  269. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/stackoverflow-light.css +0 -0
  270. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/sunburst.css +0 -0
  271. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/tokyo-night-dark.css +0 -0
  272. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/tokyo-night-light.css +0 -0
  273. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/tomorrow-night-blue.css +0 -0
  274. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/tomorrow-night-bright.css +0 -0
  275. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/vs.css +0 -0
  276. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/vs2015.css +0 -0
  277. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/xcode.css +0 -0
  278. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/css/themes/xt256.css +0 -0
  279. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/img/favicon.ico +0 -0
  280. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/img/sprites.png +0 -0
  281. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/img/trans_bg.gif +0 -0
  282. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/js/highlight.min.js +0 -0
  283. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/static/js/highlight.pack.min.js +0 -0
  284. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/templates/__init__.py +0 -0
  285. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/templates/file_diff.html +0 -0
  286. {webdiff-1.3.0b1 → webdiff-1.4.0b2}/webdiff/unified_diff.py +0 -0
@@ -1,28 +1,27 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: webdiff
3
- Version: 1.3.0b1
3
+ Version: 1.4.0b2
4
4
  Summary: Two-column web-based git difftool
5
- Home-page: https://github.com/danvk/webdiff/
6
5
  License: Apache-2.0
7
6
  Keywords: git,difftool,web
8
7
  Author: Dan Vanderkam
9
8
  Author-email: danvdk@gmail.com
10
- Requires-Python: >=3.10,<4.0
9
+ Requires-Python: >=3.12,<4.0
11
10
  Classifier: Development Status :: 4 - Beta
12
11
  Classifier: Environment :: Console
13
12
  Classifier: Environment :: Web Environment
14
13
  Classifier: Intended Audience :: Developers
15
14
  Classifier: License :: OSI Approved :: Apache Software License
16
15
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
16
  Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
20
18
  Classifier: Topic :: Software Development :: Version Control
21
19
  Requires-Dist: PyGithub (>=2.3.0,<3.0.0)
22
20
  Requires-Dist: aiohttp (>=3.9.5,<4.0.0)
23
21
  Requires-Dist: binaryornot
24
22
  Requires-Dist: pillow
25
23
  Requires-Dist: unidiff (>=0.7.4,<0.8.0)
24
+ Project-URL: Homepage, https://github.com/danvk/webdiff/
26
25
  Project-URL: Repository, https://github.com/danvk/webdiff/
27
26
  Description-Content-Type: text/markdown
28
27
 
@@ -107,6 +106,14 @@ You can also use `git webshow` in place of `git show` to show a single commit:
107
106
 
108
107
  `git webshow REF` is shorthand for `git webdiff REF^..REF`.
109
108
 
109
+ Recommended aliases:
110
+
111
+ ```bash
112
+ alias gw='git webdiff'
113
+ alias gwh='git webshow head'
114
+ alias gwdm='git webdiff $(git merge-base HEAD main)'
115
+ ```
116
+
110
117
  ## Configuration
111
118
 
112
119
  webdiff can be configured via [`git config`][git config]. To change the syntax highlighting theme, for example:
@@ -171,8 +178,9 @@ To debug `git webdiff`, run:
171
178
  To iterate on the PyPI package, run:
172
179
 
173
180
  pip3 uninstall webdiff
181
+ cd ts && yarn build && cd ..
174
182
  poetry build
175
- pip3 install dist/webdiff-?.?.?.tar.gz
183
+ pip3 install dist/webdiff-(latest).tar.gz
176
184
 
177
185
  To publish to pypitest:
178
186
 
@@ -183,6 +191,10 @@ And to the real pypi:
183
191
 
184
192
  poetry publish
185
193
 
194
+ You can publish pre-release versions to pypi by adding "bN" to the version number. To install a prerelease with `pipx`, use:
195
+
196
+ pipx install webdiff --pip-args="--pre"
197
+
186
198
  See [pypirc][] and [poetry][] docs for details on setting up tokens for pypi.
187
199
 
188
200
  Publication checklist. Do these from _outside_ the webdiff directory:
@@ -212,13 +224,16 @@ When you run `git webdiff (args)`, it runs:
212
224
 
213
225
  This tells `git` to set up two directories and invoke `webdiff leftdir rightdir`.
214
226
 
215
- There's one complication involving symlinks. `git difftool -d` may fill one of the sides (typically the right) with symlinks. This is faster than copying files, but unfortunately `git diff --no-index` does not resolve these symlinks. To make this work, if a directory contains symlinks, webdiff makes a copy of it before diffing. For file diffs, it resolves the symlink before passing it to `git diff --no-index`. The upshot is that you can run `git webdiff`, edit a file, reload the browser window and see the changes.
227
+ There are two wrinkles here:
228
+
229
+ - `git difftool -d` may fill one of the sides (typically the right) with symlinks. This is faster than copying files, but unfortunately `git diff --no-index` does not resolve these symlinks. To make this work, if a directory contains symlinks, webdiff makes a copy of it before diffing. For file diffs, it resolves the symlink before passing it to `git diff --no-index`. The upshot is that you can run `git webdiff`, edit a file, reload the browser window and see the changes.
230
+ - `git difftool` cleans up its temporary directories when the main webdiff process terminates. Since webdiff detaches to give you back your terminal, it has to make another copy of the directories (this time without resolving symlinks) to make sure they're still there for the child process.
216
231
 
217
232
  [pypirc]: https://packaging.python.org/specifications/pypirc/
218
233
  [Homebrew]: https://brew.sh/
219
234
  [ImageMagick]: https://imagemagick.org/index.php
220
235
  [git config]: https://git-scm.com/docs/git-config
221
- [themes]: http://example.com
236
+ [themes]: https://github.com/danvk/webdiff/tree/main/webdiff/static/css/themes
222
237
  [poetry]: https://python-poetry.org/docs/repositories/#publishable-repositories
223
238
  [pipx]: https://pipx.pypa.io/stable/
224
239
 
@@ -79,6 +79,14 @@ You can also use `git webshow` in place of `git show` to show a single commit:
79
79
 
80
80
  `git webshow REF` is shorthand for `git webdiff REF^..REF`.
81
81
 
82
+ Recommended aliases:
83
+
84
+ ```bash
85
+ alias gw='git webdiff'
86
+ alias gwh='git webshow head'
87
+ alias gwdm='git webdiff $(git merge-base HEAD main)'
88
+ ```
89
+
82
90
  ## Configuration
83
91
 
84
92
  webdiff can be configured via [`git config`][git config]. To change the syntax highlighting theme, for example:
@@ -143,8 +151,9 @@ To debug `git webdiff`, run:
143
151
  To iterate on the PyPI package, run:
144
152
 
145
153
  pip3 uninstall webdiff
154
+ cd ts && yarn build && cd ..
146
155
  poetry build
147
- pip3 install dist/webdiff-?.?.?.tar.gz
156
+ pip3 install dist/webdiff-(latest).tar.gz
148
157
 
149
158
  To publish to pypitest:
150
159
 
@@ -155,6 +164,10 @@ And to the real pypi:
155
164
 
156
165
  poetry publish
157
166
 
167
+ You can publish pre-release versions to pypi by adding "bN" to the version number. To install a prerelease with `pipx`, use:
168
+
169
+ pipx install webdiff --pip-args="--pre"
170
+
158
171
  See [pypirc][] and [poetry][] docs for details on setting up tokens for pypi.
159
172
 
160
173
  Publication checklist. Do these from _outside_ the webdiff directory:
@@ -184,12 +197,15 @@ When you run `git webdiff (args)`, it runs:
184
197
 
185
198
  This tells `git` to set up two directories and invoke `webdiff leftdir rightdir`.
186
199
 
187
- There's one complication involving symlinks. `git difftool -d` may fill one of the sides (typically the right) with symlinks. This is faster than copying files, but unfortunately `git diff --no-index` does not resolve these symlinks. To make this work, if a directory contains symlinks, webdiff makes a copy of it before diffing. For file diffs, it resolves the symlink before passing it to `git diff --no-index`. The upshot is that you can run `git webdiff`, edit a file, reload the browser window and see the changes.
200
+ There are two wrinkles here:
201
+
202
+ - `git difftool -d` may fill one of the sides (typically the right) with symlinks. This is faster than copying files, but unfortunately `git diff --no-index` does not resolve these symlinks. To make this work, if a directory contains symlinks, webdiff makes a copy of it before diffing. For file diffs, it resolves the symlink before passing it to `git diff --no-index`. The upshot is that you can run `git webdiff`, edit a file, reload the browser window and see the changes.
203
+ - `git difftool` cleans up its temporary directories when the main webdiff process terminates. Since webdiff detaches to give you back your terminal, it has to make another copy of the directories (this time without resolving symlinks) to make sure they're still there for the child process.
188
204
 
189
205
  [pypirc]: https://packaging.python.org/specifications/pypirc/
190
206
  [Homebrew]: https://brew.sh/
191
207
  [ImageMagick]: https://imagemagick.org/index.php
192
208
  [git config]: https://git-scm.com/docs/git-config
193
- [themes]: http://example.com
209
+ [themes]: https://github.com/danvk/webdiff/tree/main/webdiff/static/css/themes
194
210
  [poetry]: https://python-poetry.org/docs/repositories/#publishable-repositories
195
211
  [pipx]: https://pipx.pypa.io/stable/
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "webdiff"
7
- version = "1.3.0b1"
7
+ version = "1.4.0b2"
8
8
  description = "Two-column web-based git difftool"
9
9
  license = "Apache-2.0"
10
10
  readme = "README.md"
@@ -22,10 +22,12 @@ classifiers = [
22
22
  "Topic :: Software Development :: Version Control"
23
23
  ]
24
24
  # This is generated, so it's in .gitignore. But we need to package it.
25
- include = ["webdiff/static/js/file_diff.js"]
25
+ include = [
26
+ { path = "webdiff/static/js/file_diff.js", format = ["sdist", "wheel"] }
27
+ ]
26
28
 
27
29
  [tool.poetry.dependencies]
28
- python = "^3.10"
30
+ python = "^3.12"
29
31
  binaryornot = "*"
30
32
  pillow = "*"
31
33
  PyGithub = "^2.3.0"
@@ -33,8 +35,8 @@ unidiff = "^0.7.4"
33
35
  aiohttp = "^3.9.5"
34
36
 
35
37
  [tool.poetry.group.dev.dependencies]
36
- pytest = "^7.1.3"
37
- ruff = "0.7"
38
+ pytest = "^9.0"
39
+ ruff = "^0.15"
38
40
 
39
41
  [tool.poetry.scripts]
40
42
  webdiff = "webdiff.app:run"
@@ -13,6 +13,7 @@ import os
13
13
  import platform
14
14
  import signal
15
15
  import socket
16
+ import subprocess
16
17
  import sys
17
18
  import threading
18
19
  import time
@@ -24,6 +25,7 @@ from aiohttp import web
24
25
  from binaryornot.check import is_binary
25
26
 
26
27
  from webdiff import argparser, diff, options, util
28
+ from webdiff.dirdiff import make_resolved_dir
27
29
 
28
30
  VERSION = importlib.metadata.version('webdiff')
29
31
 
@@ -46,6 +48,7 @@ DIFF = None
46
48
  PORT = None
47
49
  HOSTNAME = 'localhost'
48
50
  DEBUG = os.environ.get('DEBUG')
51
+ DEBUG_DETACH = os.environ.get('DEBUG_DETACH')
49
52
  WEBDIFF_DIR = determine_path()
50
53
 
51
54
  if DEBUG:
@@ -273,15 +276,8 @@ def pick_a_port(args, webdiff_config):
273
276
 
274
277
 
275
278
  def run_http():
276
- sys.stderr.write(
277
- """Serving diffs on http://%s:%s
278
- Close the browser tab or hit Ctrl-C when you're done.
279
- """
280
- % (HOSTNAME, PORT)
281
- )
282
279
  threading.Timer(0.1, open_browser).start()
283
-
284
- web.run_app(app, host=HOSTNAME, port=PORT)
280
+ web.run_app(app, host=HOSTNAME, port=PORT, print=print if DEBUG else None)
285
281
  logging.debug('http server shut down')
286
282
 
287
283
 
@@ -291,7 +287,7 @@ def maybe_shutdown():
291
287
 
292
288
  def shutdown():
293
289
  if LAST_REQUEST_MS <= last_ms: # subsequent requests abort shutdown
294
- sys.stderr.write('Shutting down...\n')
290
+ logging.debug('Shutting down...')
295
291
  signal.raise_signal(signal.SIGINT)
296
292
  else:
297
293
  logging.debug('Received subsequent request; shutdown aborted.')
@@ -334,7 +330,36 @@ def run():
334
330
  else:
335
331
  HOSTNAME = _hostname
336
332
 
337
- run_http()
333
+ run_in_process = os.environ.get('WEBDIFF_RUN_IN_PROCESS') or (
334
+ DEBUG and not DEBUG_DETACH
335
+ )
336
+
337
+ if not os.environ.get('WEBDIFF_LOGGED_MESSAGE'):
338
+ # Printing this in the main process gives you your prompt back more cleanly.
339
+ print(
340
+ """Serving diffs on http://%s:%s
341
+ Close the browser tab when you're done to terminate the process."""
342
+ % (HOSTNAME, PORT)
343
+ )
344
+ os.environ['WEBDIFF_LOGGED_MESSAGE'] = '1'
345
+
346
+ if run_in_process:
347
+ run_http()
348
+ else:
349
+ os.environ['WEBDIFF_RUN_IN_PROCESS'] = '1'
350
+ os.environ['WEBDIFF_PORT'] = str(PORT)
351
+ if os.environ.get('WEBDIFF_FROM_GIT_DIFFTOOL'):
352
+ # git difftool will clean up these directories when we detach.
353
+ # To make them accessible to the child process, we make a (shallow) copy.
354
+ assert 'dirs' in parsed_args
355
+ dir_a, dir_b = parsed_args['dirs']
356
+ copied_dir_a = make_resolved_dir(dir_a)
357
+ copied_dir_b = make_resolved_dir(dir_b)
358
+ os.environ['WEBDIFF_DIR_A'] = copied_dir_a
359
+ os.environ['WEBDIFF_DIR_B'] = copied_dir_b
360
+ logging.debug(f'Copied {dir_a} -> {copied_dir_a} before detaching')
361
+ logging.debug(f'Copied {dir_b} -> {copied_dir_b} before detaching')
362
+ subprocess.Popen((sys.executable, *sys.argv))
338
363
 
339
364
 
340
365
  if __name__ == '__main__':
@@ -4,9 +4,7 @@ import argparse
4
4
  import os
5
5
  import re
6
6
 
7
- from webdiff import dirdiff
8
- from webdiff import githubdiff
9
- from webdiff import github_fetcher
7
+ from webdiff import dirdiff, github_fetcher, githubdiff
10
8
  from webdiff.localfilediff import LocalFileDiff
11
9
 
12
10
 
@@ -81,6 +79,12 @@ def parse(args, version=None):
81
79
 
82
80
  else:
83
81
  a, b = args.dirs
82
+ if os.environ.get('WEBDIFF_DIR_A') and os.environ.get('WEBDIFF_DIR_B'):
83
+ # This happens when you run "git webdiff" and we have to make a copy of
84
+ # the temp directories before we detach and git difftool cleans them up.
85
+ a = os.environ.get('WEBDIFF_DIR_A')
86
+ b = os.environ.get('WEBDIFF_DIR_B')
87
+
84
88
  for x in (a, b):
85
89
  if not os.path.exists(x):
86
90
  raise UsageError('"%s" does not exist' % x)
@@ -42,7 +42,12 @@ def fast_num_lines(path: str) -> int:
42
42
  # See https://stackoverflow.com/q/9629179/388951 for the idea to use a Unix command.
43
43
  # Unfortunately `wc -l` ignores the last line if there is no trailing newline. So
44
44
  # instead, see https://stackoverflow.com/a/38870057/388951
45
- return int(subprocess.check_output(['grep', '-c', '', path]))
45
+ try:
46
+ return int(subprocess.check_output(['grep', '-c', '', path]))
47
+ except subprocess.CalledProcessError as e:
48
+ if e.returncode == 1:
49
+ return 0 # grep -c returns an error code if there are no matches
50
+ raise
46
51
 
47
52
 
48
53
  def get_diff_ops(
@@ -1,7 +1,7 @@
1
1
  """Compute the diff between two directories on local disk."""
2
2
 
3
- import os
4
3
  import logging
4
+ import os
5
5
  import shutil
6
6
  import subprocess
7
7
  import tempfile
@@ -27,7 +27,7 @@ def contains_symlinks(dir: str):
27
27
  return False
28
28
 
29
29
 
30
- def make_resolved_dir(dir: str) -> str:
30
+ def make_resolved_dir(dir: str, follow_symlinks=False) -> str:
31
31
  # TODO: clean up this directory
32
32
  temp_dir = tempfile.mkdtemp(prefix='webdiff')
33
33
  for root, dirs, files in os.walk(dir):
@@ -38,7 +38,7 @@ def make_resolved_dir(dir: str) -> str:
38
38
  src_file = os.path.join(root, file_name)
39
39
  rel = os.path.relpath(src_file, dir)
40
40
  dst_file = os.path.join(temp_dir, rel)
41
- shutil.copy(src_file, dst_file, follow_symlinks=True)
41
+ shutil.copy(src_file, dst_file, follow_symlinks=follow_symlinks)
42
42
  return temp_dir
43
43
 
44
44
 
@@ -49,11 +49,11 @@ def gitdiff(a_dir: str, b_dir: str, webdiff_config):
49
49
  cmd += ' ' + extra_args
50
50
  a_dir_nosym = a_dir
51
51
  if contains_symlinks(a_dir):
52
- a_dir_nosym = make_resolved_dir(a_dir)
52
+ a_dir_nosym = make_resolved_dir(a_dir, follow_symlinks=True)
53
53
  logging.debug(f'Inlined symlinks in left directory {a_dir} -> {a_dir_nosym}')
54
54
  b_dir_nosym = b_dir
55
55
  if contains_symlinks(b_dir):
56
- b_dir_nosym = make_resolved_dir(b_dir)
56
+ b_dir_nosym = make_resolved_dir(b_dir, follow_symlinks=True)
57
57
  logging.debug(f'Inlined symlinks in right directory {b_dir} -> {b_dir_nosym}')
58
58
  args = cmd.split(' ') + [a_dir_nosym, b_dir_nosym]
59
59
  logging.debug('Running git command: %s', args)
@@ -6,11 +6,11 @@ This will create symlinks or clone git repos as needed.
6
6
  # Use this PR for testing to see all four types of change at once:
7
7
  # https://github.com/danvk/test-repo/pull/2/
8
8
 
9
- from collections import OrderedDict
10
9
  import os
11
10
  import re
12
11
  import subprocess
13
12
  import sys
13
+ from collections import OrderedDict
14
14
 
15
15
  from github import Github, UnknownObjectException
16
16
 
@@ -138,7 +138,7 @@ def _get_github_remotes():
138
138
 
139
139
  # e.g. 'origin git@github.com:danvk/expandable-image-grid.git (push)'
140
140
  ssh_push_re = re.compile(
141
- '(?P<name>[^\s]+)\s+((?P<user>[^@]+)@)?(?P<host>[^:]+)(?::(?P<path>[^\s]+))?\s\(push\)'
141
+ r'(?P<name>[^\s]+)\s+((?P<user>[^@]+)@)?(?P<host>[^:]+)(?::(?P<path>[^\s]+))?\s\(push\)'
142
142
  )
143
143
 
144
144
  # e.g. 'origin https://github.com/danvk/git-helpers.git (push)'
@@ -21,6 +21,7 @@ def run(argv=sys.argv):
21
21
  if not os.environ.get('DEBUG')
22
22
  else os.path.join(os.path.curdir, 'test.sh')
23
23
  )
24
+ os.environ['WEBDIFF_FROM_GIT_DIFFTOOL'] = '1'
24
25
  subprocess.call(f'git difftool -d -x {cmd}'.split(' ') + argv[1:])
25
26
  except KeyboardInterrupt:
26
27
  # Don't raise an exception to the user when sigint is received
@@ -66,6 +66,12 @@ table.diff tr.skip-row td {
66
66
  padding: 0.5em;
67
67
  }
68
68
 
69
+ /* Partially collapse empty sides of diffs */
70
+ .diff.diff-add td.before,
71
+ .diff.diff-delete td.after {
72
+ width: 51ch;
73
+ }
74
+
69
75
  .line-no, .code {
70
76
  padding: 2px;
71
77
  height: 1.11em;
@@ -154,3 +160,53 @@ span.skip {
154
160
  -ms-user-select: text;
155
161
  user-select: text;
156
162
  }
163
+
164
+ a, a:visited {
165
+ text-decoration: none;
166
+ color: #00a;
167
+ }
168
+
169
+ tr.skip-row {
170
+ position: relative;
171
+ line-height: 1.5em;
172
+ }
173
+ .skip.right {
174
+ position: absolute;
175
+ }
176
+ .skip.right {
177
+ right: 32px;
178
+ }
179
+ .skip.expand-up, .skip.expand-down {
180
+ font-size: 12px;
181
+ font-family: Inconsolata, Consolas, "Liberation Mono", Menlo, Courier, monospace;
182
+ color: #aaa;
183
+ background: #fff;
184
+ border: 1px solid #e8e8e8;
185
+ padding: 0px 5px;
186
+ cursor: pointer;
187
+ white-space: nowrap;
188
+ display: inline-block;
189
+ line-height: 1.3;
190
+ letter-spacing: 0.04em;
191
+ }
192
+ .skip.expand-up:hover, .skip.expand-down:hover {
193
+ background: #f5f5f5;
194
+ color: #888;
195
+ border-color: #ccc;
196
+ }
197
+ /* tab hangs down from the row above: no top border, rounded bottom corners */
198
+ .skip.expand-up {
199
+ top: 0;
200
+ border-top: none;
201
+ border-radius: 0 0 4px 4px;
202
+ }
203
+ /* tab sticks up from the row below: no bottom border, rounded top corners */
204
+ .skip.expand-down {
205
+ bottom: 0;
206
+ border-bottom: none;
207
+ border-radius: 4px 4px 0 0;
208
+ }
209
+
210
+ a.show-more {
211
+ color: #888;
212
+ }
@@ -44,6 +44,10 @@ td.code {
44
44
  width: 101ch; /* per-side max line length */
45
45
  }
46
46
 
47
+ .code.equal.expanded {
48
+ background-color: #f7f7f7;
49
+ }
50
+
47
51
  .file-selector {
48
52
  padding-bottom: 5px;
49
53
  border-bottom: 1px solid #ccc;
@@ -106,29 +110,30 @@ ul.file-list {
106
110
  .side-a { border: 1px solid red; }
107
111
  .side-b { border: 1px solid green; }
108
112
 
109
- .image-diff-controls {
113
+ /* Per-file type diff controls: image diff mode, JSON normalization */
114
+ .diff-mode-controls {
110
115
  text-align: center;
111
116
  background-color: #f7f7f7;
112
117
  padding: 5px;
113
118
  }
114
- .image-diff-controls > input {
119
+ .diff-mode-controls > input {
115
120
  margin-left: 20px;
116
121
  }
117
- .image-diff-controls a {
122
+ .diff-mode-controls a {
118
123
  text-decoration: none;
119
124
  }
120
- .image-diff-controls a, .image-diff-controls a:visited {
125
+ .diff-mode-controls a, .diff-mode-controls a:visited {
121
126
  color: #666;
122
127
  }
123
- .image-diff-controls b {
128
+ .diff-mode-controls b {
124
129
  color: black;
125
130
  }
126
- .image-diff-controls .mode {
131
+ .diff-mode-controls .mode {
127
132
  padding-left: 5px;
128
133
  padding-right: 5px;
129
134
  border-right: 1px solid #ccc;
130
135
  }
131
- .image-diff-controls .mode:last-child {
136
+ .diff-mode-controls .mode:last-child {
132
137
  border-right: none;
133
138
  }
134
139
 
@@ -245,3 +250,8 @@ kbd {
245
250
  list-style-type: none;
246
251
  margin-bottom: 2px;
247
252
  }
253
+
254
+ .suppressed-large-diff {
255
+ text-align: center;
256
+ background-color: lightyellow;
257
+ }