diff_command.ex (4146B)
1 defmodule Credo.CLI.Command.Diff.DiffCommand do 2 @moduledoc false 3 4 alias Credo.CLI.Command.Diff.DiffOutput 5 alias Credo.CLI.Switch 6 alias Credo.CLI.Task 7 alias Credo.Execution 8 9 alias Credo.CLI.Command.Diff.Task.FilterIssues 10 alias Credo.CLI.Command.Diff.Task.FilterIssuesForExitStatus 11 alias Credo.CLI.Command.Diff.Task.GetGitDiff 12 alias Credo.CLI.Command.Diff.Task.PrintBeforeInfo 13 alias Credo.CLI.Command.Diff.Task.PrintResultsAndSummary 14 15 use Credo.CLI.Command, 16 short_description: "Suggest code objects to look at next (based on git-diff)", 17 cli_switches: 18 Credo.CLI.Command.Suggest.SuggestCommand.cli_switches() ++ 19 [ 20 Switch.string("from_dir"), 21 Switch.string("from_git_ref"), 22 Switch.string("from_git_merge_base"), 23 Switch.boolean("show_fixed"), 24 Switch.boolean("show_kept"), 25 Switch.string("since") 26 ] 27 28 def init(exec) do 29 Execution.put_pipeline(exec, "diff", 30 load_and_validate_source_files: [ 31 {Task.LoadAndValidateSourceFiles, []} 32 ], 33 prepare_analysis: [ 34 {Task.PrepareChecksToRun, []} 35 ], 36 print_previous_analysis: [ 37 {GetGitDiff, []}, 38 {PrintBeforeInfo, []} 39 ], 40 run_analysis: [ 41 {Task.RunChecks, []} 42 ], 43 filter_issues: [ 44 {Task.SetRelevantIssues, []}, 45 {FilterIssues, []} 46 ], 47 print_after_analysis: [ 48 {PrintResultsAndSummary, []} 49 ], 50 filter_issues_for_exit_status: [ 51 {FilterIssuesForExitStatus, []} 52 ] 53 ) 54 end 55 56 def call(%Execution{help: true} = exec, _opts), do: DiffOutput.print_help(exec) 57 def call(exec, _opts), do: Execution.run_pipeline(exec, __MODULE__) 58 59 def previous_ref(exec) do 60 case exec.cli_options.switches do 61 %{since: given_datetime} -> 62 previous_ref_as_datetime(given_datetime) || 63 {:error, "given value is not a valid commit date: #{given_datetime}"} 64 65 %{from_dir: given_dir} -> 66 previous_ref_as_path(given_dir) || 67 {:error, "given value is not a local directory: #{given_dir}"} 68 69 %{from_git_ref: given_git_ref} -> 70 previous_ref_as_git_ref(given_git_ref) || 71 {:error, "given value is not a Git ref: #{given_git_ref}"} 72 73 %{from_git_merge_base: given_git_merge_base} -> 74 previous_ref_as_git_merge_base(given_git_merge_base) || 75 {:error, "given value is not a Git ref: #{given_git_merge_base}"} 76 77 _ -> 78 given_first_arg = List.first(exec.cli_options.args) 79 80 previous_ref_from_first_arg(given_first_arg) || 81 {:error, "given ref is not a Git ref or local path: #{given_first_arg}"} 82 end 83 end 84 85 defp previous_ref_from_first_arg(nil) do 86 previous_ref_as_git_ref("HEAD") 87 end 88 89 defp previous_ref_from_first_arg(given_first_arg) do 90 previous_ref_as_git_ref(given_first_arg) || 91 previous_ref_as_path(given_first_arg) 92 end 93 94 def previous_ref_as_datetime(potential_datetime) do 95 if git_present?() do 96 {:git_datetime, potential_datetime} 97 else 98 {:error, "could not run `git`"} 99 end 100 end 101 102 def previous_ref_as_git_ref(potential_git_ref) do 103 if git_present?() do 104 if git_ref_exists?(potential_git_ref) do 105 {:git, potential_git_ref} 106 end 107 else 108 {:error, "could not run `git`"} 109 end 110 end 111 112 def previous_ref_as_git_merge_base(potential_git_ref) do 113 if git_present?() do 114 if git_ref_exists?(potential_git_ref) do 115 {:git_merge_base, potential_git_ref} 116 end 117 else 118 {:error, "could not run `git`"} 119 end 120 end 121 122 def previous_ref_as_path(potential_path) do 123 if File.exists?(potential_path) do 124 {:path, potential_path} 125 else 126 {:error, "could not find given path: #{potential_path}"} 127 end 128 end 129 130 defp git_present? do 131 case System.cmd("git", ["--help"], stderr_to_stdout: true) do 132 {_output, 0} -> true 133 {_output, _} -> false 134 end 135 rescue 136 _ -> false 137 end 138 139 defp git_ref_exists?(git_ref) do 140 case System.cmd("git", ["show", git_ref], stderr_to_stdout: true) do 141 {_output, 0} -> true 142 {_output, _} -> false 143 end 144 end 145 end