text.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. """Ensure text files have the proper line endings.
  2. """
  3. from itertools import islice
  4. from subprocess import DEVNULL
  5. from milc import cli
  6. from qmk.path import normpath, is_relative_to
  7. IGNORE_SUFFIXES = [
  8. 'hex',
  9. 'ico',
  10. 'jpeg',
  11. 'jpg',
  12. 'png',
  13. ]
  14. IGNORE_DIRS = [
  15. 'lib/fnv',
  16. 'lib/lib8tion',
  17. 'lib/usbhost',
  18. ]
  19. def _get_chunks(it, size):
  20. """Break down a collection into smaller parts
  21. """
  22. it = iter(it)
  23. return iter(lambda: tuple(islice(it, size)), ())
  24. def _check_dos2unix():
  25. """Check for a 'valid' dos2unix executable
  26. """
  27. dos2unix = cli.run(['dos2unix', '--help'])
  28. return dos2unix.returncode == 0 and '--add-eol' in dos2unix.stdout
  29. def dos2unix_run(files):
  30. """Spawn multiple dos2unix subprocess avoiding too long commands on formatting everything
  31. """
  32. for chunk in _get_chunks([normpath(file).as_posix() for file in files], 10):
  33. dos2unix = cli.run(['dos2unix', '--add-eol', *chunk])
  34. if dos2unix.returncode:
  35. cli.log.debug(dos2unix.stdout)
  36. cli.log.error(dos2unix.stderr)
  37. return False
  38. def filter_files(files):
  39. """Yield only files to be formatted and skip the rest
  40. """
  41. ret = []
  42. for file in map(normpath, filter(None, files)):
  43. if file.suffix[1:] in IGNORE_SUFFIXES:
  44. continue
  45. if not any(is_relative_to(file, i) for i in IGNORE_DIRS):
  46. ret.append(file)
  47. return ret
  48. @cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.')
  49. @cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all files.')
  50. @cli.argument('files', nargs='*', arg_only=True, type=normpath, help='Filename(s) to format.')
  51. @cli.subcommand("Ensure text files have the proper line endings.", hidden=True)
  52. def format_text(cli):
  53. """Ensure text files have the proper line endings.
  54. """
  55. if not _check_dos2unix():
  56. cli.log.error('Formatting requires an up-to-date version of "dos2unix"')
  57. return False
  58. # Find the list of files to format
  59. if cli.args.files:
  60. files = filter_files(cli.args.files)
  61. if not files:
  62. cli.log.error('No valid files in filelist: %s', ', '.join(map(str, cli.args.files)))
  63. return False
  64. if cli.args.all_files:
  65. cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(map(str, files)))
  66. elif cli.args.all_files:
  67. git_ls_cmd = ['git', 'ls-files']
  68. git_ls = cli.run(git_ls_cmd, stdin=DEVNULL)
  69. files = filter_files(git_ls.stdout.split('\n'))
  70. else:
  71. git_diff_cmd = ['git', 'diff', '--name-only', cli.args.base_branch]
  72. git_diff = cli.run(git_diff_cmd, stdin=DEVNULL)
  73. files = filter_files(git_diff.stdout.split('\n'))
  74. # Sanity check
  75. if not files:
  76. cli.log.error('No changed files detected. Use "qmk format-text -a" to format all files')
  77. return False
  78. return dos2unix_run(files)