ronantakizawa/codereview-bench huggingface dataset:
Repository: jerryscript-project/jerryscript
File: jerry-core/lit/lit-strings.c (C)

Code before:
    if (first_byte < LIT_UTF8_3_BYTE_MARKER)
    {
      continue;
    }

    if (idx >= end || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER)
    {
      return false;
    }

    if (first_byte < LIT_UTF8_4_BYTE_MARKER)
    {
      if (first_byte == LIT_UTF8_3_BYTE_MARKER && (second_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER)
      {
        return false;
      }

      if (is_strict
          && first_byte == LIT_UTF8_SURROGATE_MARKER
          && second_byte >= LIT_UTF8_HIGH_SURROGATE_MIN
          && second_byte <= LIT_UTF8_HIGH_SURROGATE_MAX
          && idx + 3 <= end
          && idx[0] == LIT_UTF8_SURROGATE_MARKER
          && idx[1] >= LIT_UTF8_LOW_SURROGATE_MIN
          && idx[1] <= LIT_UTF8_LOW_SURROGATE_MAX
          && ((idx[2] & LIT_UTF8_EXTRA_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER))
      {
        return false;
      }
      continue;
    }

    if (idx >= end
        || first_byte > LIT_UTF8_1_BYTE_MAX
        || (first_byte == LIT_UTF8_4_BYTE_MARKER && second_byte <= LIT_UTF8_EXTRA_BYTE_MARKER)
        || (first_byte == LIT_UTF8_1_BYTE_MAX && second_byte > LIT_UTF8_2_BYTE_MAX)
        || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER)
    {
      return false;
    }
  }

  return true;
} /* lit_is_valid_utf8_string */

/**
 * Validate cesu-8 string
 *
 * @return true if cesu-8 string is well-formed
 *         false otherwise
 */

Review comment (suggestion):
The last character (`idx[2]`) does not matter (either invalid, or valid, but low surrogate), this check is unnecessary. 

Code after:
    if (first_byte < LIT_UTF8_3_BYTE_MARKER)
    {
      continue;
    }

    if (idx >= end || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER)
    {
      return false;
    }

    if (first_byte < LIT_UTF8_4_BYTE_MARKER)
    {
      if (first_byte == LIT_UTF8_3_BYTE_MARKER && (second_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_EXTRA_BYTE_MARKER)
      {
        return false;
      }

      if (is_strict
          && first_byte == LIT_UTF8_SURROGATE_MARKER
          && second_byte >= LIT_UTF8_HIGH_SURROGATE_MIN
          && second_byte <= LIT_UTF8_HIGH_SURROGATE_MAX
          && idx + 3 <= end
          && idx[0] == LIT_UTF8_SURROGATE_MARKER
          && idx[1] >= LIT_UTF8_LOW_SURROGATE_MIN
          && idx[1] <= LIT_UTF8_LOW_SURROGATE_MAX)
      {
        return false;
      }
      continue;
    }

    if (idx >= end
        || first_byte > LIT_UTF8_1_BYTE_MAX
        || (first_byte == LIT_UTF8_4_BYTE_MARKER && second_byte <= LIT_UTF8_EXTRA_BYTE_MARKER)
        || (first_byte == LIT_UTF8_1_BYTE_MAX && second_byte > LIT_UTF8_2_BYTE_MAX)
        || (*idx++ & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER)
    {
      return false;
    }
  }

  return true;
} /* lit_is_valid_utf8_string */

/**
 * Validate cesu-8 string
 *
 * @return true if cesu-8 string is well-formed
 *         false otherwise
 */
bool
Repository: jerryscript-project/jerryscript
File: jerry-core/parser/js/js-parser-statm.c (C)

Code before:
#if JERRY_ESNEXT
      case LEXER_LITERAL:
      {
        if (!lexer_token_is_let (context_p))
        {
          parser_parse_expression_statement (context_p, PARSE_EXPR);
          break;
        }

        if (context_p->next_scanner_info_p->source_p == context_p->source_p
            && context_p->next_scanner_info_p->type != SCANNER_TYPE_BLOCK)
        {
          if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION)
          {
            scanner_release_next (context_p, sizeof (scanner_info_t));
          }

          parser_parse_expression_statement (context_p, PARSE_EXPR);
          break;
        }

        context_p->token.type = LEXER_KEYW_LET;
        /* FALLTHRU */
      }
      case LEXER_KEYW_LET:
      {
        if (context_p->next_scanner_info_p->source_p == source_p
            && context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK)
        {
          parser_push_block_context (context_p, true);
        }

        parser_parse_var_statement (context_p);
        break;
      }
      case LEXER_KEYW_CONST:
      {
        if (context_p->next_scanner_info_p->source_p == source_p)
        {
          parser_push_block_context (context_p, true);
        }
        /* FALLTHRU */
      }
#endif /* JERRY_ESNEXT */
      case LEXER_KEYW_VAR:
      {
        parser_parse_var_statement (context_p);
        break;
      }
      default:
      {

Review comment (suggestion):
Move the `LEXER_KEYW_LET` before `if (context_p->next_scanner_info_p->source_p == context_p->source_p`.

Code after:
    {
#if JERRY_ESNEXT
      case LEXER_LITERAL:
      {
        if (!lexer_token_is_let (context_p))
        {
          parser_parse_expression_statement (context_p, PARSE_EXPR);
          break;
        }

        /* FALLTHRU */
      }
      case LEXER_KEYW_LET:
      {
        if (context_p->next_scanner_info_p->source_p == context_p->source_p
            && context_p->next_scanner_info_p->type != SCANNER_TYPE_BLOCK)
        {
          if (context_p->next_scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION)
          {
            scanner_release_next (context_p, sizeof (scanner_info_t));
          }

          parser_parse_expression_statement (context_p, PARSE_EXPR);
          break;
        }

        context_p->token.type = LEXER_KEYW_LET;

        /* FALLTHRU */
      }
      case LEXER_KEYW_CONST:
      {
        if (context_p->next_scanner_info_p->source_p == source_p)
        {
          parser_push_block_context (context_p, true);
        }
        /* FALLTHRU */
      }
#endif /* JERRY_ESNEXT */
      case LEXER_KEYW_VAR:
      {
        parser_parse_var_statement (context_p);
        break;
      }
      default:
      {
        parser_parse_expression_statement (context_p, PARSE_EXPR);
        break;
      }
    }
Repository: jerryscript-project/jerryscript
File: tests/jerry/es.next/object-hasown.js (JavaScript)

Code before:
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var obj = { "foo": 5 }

assert(Object.hasOwn(obj, "foo") == true)
assert(Object.hasOwn(obj, "bar") == false)

const handler1 = {};

const handler2 = {
    getOwnPropertyDescriptor: function (target, prop, receiver) {
        return { configurable: true, enumerable: true, value: true };
    }
};

const handler3 = {
    getOwnPropertyDescriptor: function (target, prop, receiver) {
    }
};

const proxy1 = new Proxy(obj, handler1);
const proxy2 = new Proxy(obj, handler2);
const proxy3 = new Proxy(obj, handler3);

assert(Object.hasOwn(proxy1, "foo") == true)
assert(Object.hasOwn(proxy1, "bar") == false)

assert(Object.hasOwn(proxy2, "foo") == true)
assert(Object.hasOwn(proxy2, "bar") == true)

assert(Object.hasOwn(proxy3, "foo") == false)
assert(Object.hasOwn(proxy3, "bar") == false)



Review comment (suggestion):
please add test for Object.hasOwn.call(undefined), and `Object.hasOwn.call({}, {get toString() { throw new Error()}})`

Code after:
    }
};

const handler3 = {
    getOwnPropertyDescriptor(target, prop, receiver) { }
};

const proxy1 = new Proxy(obj, handler1);
const proxy2 = new Proxy(obj, handler2);
const proxy3 = new Proxy(obj, handler3);

assert(Object.hasOwn(proxy1, "foo") == true);
assert(Object.hasOwn(proxy1, "bar") == false);

assert(Object.hasOwn(proxy2, "foo") == true);
assert(Object.hasOwn(proxy2, "bar") == true);

assert(Object.hasOwn(proxy3, "foo") == false);
assert(Object.hasOwn(proxy3, "bar") == false);

try {
    Object.hasOwn({}, { get toString() { throw "foo" } });
} catch (e) {
    assert(e === "foo");
}

try {
    Object.hasOwn(undefined);
    assert(false);
} catch (e) {
    assert(e instanceof TypeError);
}
Repository: jerryscript-project/jerryscript
File: tests/jerry/es.next/arguments.js (JavaScript)

Code before:
  assert(e("arguments[0]") === 4.5)
  assert(e("arguments[1]") === "A")
  assert(arguments === -12.5)
}
f19(undefined, "A");

function f20 (arguments, a = eval('arguments')) {
  assert(a === 3.1);
  assert(arguments === 3.1);
}
f20(3.1);

function f21 (arguments, a = arguments) {
  assert(a === 3.1);
  assert(arguments === 3.1);
}
f21(3.1);

function f22 (arguments, [a = arguments]) {
  assert(a === 3.1);
  assert(arguments === 3.1);
}
f22(3.1, []);

function f23(arguments, eval = () => eval()) {
  assert(arguments === 3.1);
}
f23(3.1);


Review comment (suggestion):
I would prefer an undefined comparison to prove that the arguments object has never been created (and not overwritten later by the number argument)

Code after:
  assert(e("arguments[0]") === 4.5)
  assert(e("arguments[1]") === "A")
  assert(arguments === -12.5)
}
f19(undefined, "A");

function f20 (arguments, a = eval('arguments')) {
  assert(a === 3.1);
  assert(arguments === 3.1);
}
f20(3.1);

function f21 (arguments, a = arguments) {
  assert(a === 3.1);
  assert(arguments === 3.1);
}
f21(3.1);

function f22 (arguments, [a = arguments]) {
  assert(a === 3.1);
  assert(arguments === 3.1);
}
f22(3.1, []);

function f23(arguments, eval = () => eval()) {
  assert(arguments === undefined);
}
f23(undefined);
Repository: jesseduffield/lazygit
File: pkg/i18n/english.go (Go)

Code before:
			ID:    "commitChangesWithoutHook",
			Other: "commit changes without pre-commit hook",
		}, &i18n.Message{
			ID:    "SkipHookPrefixNotConfigured",
			Other: "You have not configured a commit message prefix for skipping hooks. Set `git.skipHookPrefix = 'WIP'` in your config",
		}, &i18n.Message{
			ID:    "resetTo",
			Other: `reset to`,
		}, &i18n.Message{
			ID:    "pressEnterToReturn",
			Other: "Press enter to return to lazygit",
		}, &i18n.Message{
			ID:    "viewStashOptions",
			Other: "view stash options",
		}, &i18n.Message{
			ID:    "stashAllChanges",
			Other: "stash changes",
		}, &i18n.Message{
			ID:    "stashStagedChanges",
			Other: "stash staged changes",
		}, &i18n.Message{
			ID:    "stashOptions",
			Other: "Stash options",
		}, &i18n.Message{
			ID:    "notARepository",
			Other: "Error: must be run inside a repository",
		},
	)
}


Review comment (suggestion):
I think "Error: must be run inside a **git** repository" is a better choice, there are more things that are called a repository.

Code after:
			ID:    "commitChangesWithoutHook",
			Other: "commit changes without pre-commit hook",
		}, &i18n.Message{
			ID:    "SkipHookPrefixNotConfigured",
			Other: "You have not configured a commit message prefix for skipping hooks. Set `git.skipHookPrefix = 'WIP'` in your config",
		}, &i18n.Message{
			ID:    "resetTo",
			Other: `reset to`,
		}, &i18n.Message{
			ID:    "pressEnterToReturn",
			Other: "Press enter to return to lazygit",
		}, &i18n.Message{
			ID:    "viewStashOptions",
			Other: "view stash options",
		}, &i18n.Message{
			ID:    "stashAllChanges",
			Other: "stash changes",
		}, &i18n.Message{
			ID:    "stashStagedChanges",
			Other: "stash staged changes",
		}, &i18n.Message{
			ID:    "stashOptions",
			Other: "Stash options",
		}, &i18n.Message{
			ID:    "notARepository",
			Other: "Error: must be run inside a git repository",
		},
	)
}
Repository: jesseduffield/lazygit
File: pkg/gui/gui.go (Go)

Code before:

// Run setup the gui with keybindings and start the mainloop
func (gui *Gui) Run() error {
	g, err := gocui.NewGui(gocui.OutputNormal, OverlappingEdges)
	if err != nil {
		return err
	}
	defer g.Close()

	if gui.Config.GetUserConfig().GetBool("gui.mouseEvents") {
		g.Mouse = true
	}

	gui.g = g // TODO: always use gui.g rather than passing g around everywhere

	if err := gui.SetColorScheme(); err != nil {
		return err
	}

	if gui.Config.GetUserConfig().GetString("reporting") == "undetermined" {
		gui.waitForIntro.Add(2)
	} else {
		gui.waitForIntro.Add(1)
	}

	if gui.Config.GetUserConfig().GetBool("gui.git.autoFetch") {
		go gui.startBackgroundFetch()
	}
	gui.goEvery(time.Second*10, gui.refreshFiles)
	gui.goEvery(time.Millisecond*50, gui.renderAppStatus)

	g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout()))

	if err = gui.keybindings(g); err != nil {
		return err
	}

	err = g.MainLoop()
	return err
}

// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
// if the error returned from a run is a ErrSubProcess, it runs the subprocess
// otherwise it handles the error, possibly by quitting the application
func (gui *Gui) RunWithSubprocesses() error {
	for {
		if err := gui.Run(); err != nil {
			if err == gocui.ErrQuit {
				break
			} else if err == gui.Errors.ErrSwitchRepo {
				continue

Review comment (suggestion):
we already have a top-level `git` key for the config options so I think this should be "git.autoFetch" and so we'd need to update app_config.go accordingly

Code after:

// Run setup the gui with keybindings and start the mainloop
func (gui *Gui) Run() error {
	g, err := gocui.NewGui(gocui.OutputNormal, OverlappingEdges)
	if err != nil {
		return err
	}
	defer g.Close()

	if gui.Config.GetUserConfig().GetBool("gui.mouseEvents") {
		g.Mouse = true
	}

	gui.g = g // TODO: always use gui.g rather than passing g around everywhere

	if err := gui.SetColorScheme(); err != nil {
		return err
	}

	if gui.Config.GetUserConfig().GetString("reporting") == "undetermined" {
		gui.waitForIntro.Add(2)
	} else {
		gui.waitForIntro.Add(1)
	}

	if gui.Config.GetUserConfig().GetBool("git.autoFetch") {
		go gui.startBackgroundFetch()
	}
	gui.goEvery(time.Second*10, gui.refreshFiles)
	gui.goEvery(time.Millisecond*50, gui.renderAppStatus)

	g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout()))

	if err = gui.keybindings(g); err != nil {
		return err
	}

	err = g.MainLoop()
	return err
}

// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
// if the error returned from a run is a ErrSubProcess, it runs the subprocess
// otherwise it handles the error, possibly by quitting the application
func (gui *Gui) RunWithSubprocesses() error {
	for {
		if err := gui.Run(); err != nil {
			if err == gocui.ErrQuit {
				break
			} else if err == gui.Errors.ErrSwitchRepo {
				continue
Repository: jesseduffield/lazygit
File: pkg/updates/updates.go (Go)

Code before:
func (u *Updater) Update(newVersion string, onFinish func(error) error) {
	go func() {
		err := u.update(newVersion)
		if err = onFinish(err); err != nil {
			u.Log.Error(err)
		}
	}()
}

func (u *Updater) update(newVersion string) error {
	rawUrl, err := u.getBinaryUrl(newVersion)
	if err != nil {
		return err
	}
	u.Log.Info("Updating with url " + rawUrl)
	return u.downloadAndInstall(rawUrl)
}

func (u *Updater) downloadAndInstall(rawUrl string) error {
	url, err := url.Parse(rawUrl)
	if err != nil {
		return err
	}

	g := new(getter.HttpGetter)
	configDir := filepath.Dir(u.Config.GetUserConfigPath())
	u.Log.Info("Download directory is " + configDir)

	// Get it!
	if err := g.Get(configDir, url); err != nil {
		return err
	}

	// get the path of the current binary
	binaryPath, err := osext.Executable()
	if err != nil {
		return err
	}
	u.Log.Info("Binary path is " + binaryPath)

	binaryName := filepath.Base(binaryPath)
	u.Log.Info("Binary name is " + binaryName)

	// Verify the main file exists
	tempPath := filepath.Join(configDir, binaryName)
	u.Log.Info("Temp path to binary is " + tempPath)
	if _, err := os.Stat(tempPath); err != nil {
		return err
	}

	// swap out the old binary for the new one

Review comment (suggestion):
I wonder if it's worth having u.Config.GetUserConfigDir() rather than `Path()` given we'll often end up calling `.Dir` on it

Code after:
func (u *Updater) Update(newVersion string, onFinish func(error) error) {
	go func() {
		err := u.update(newVersion)
		if err = onFinish(err); err != nil {
			u.Log.Error(err)
		}
	}()
}

func (u *Updater) update(newVersion string) error {
	rawUrl, err := u.getBinaryUrl(newVersion)
	if err != nil {
		return err
	}
	u.Log.Info("Updating with url " + rawUrl)
	return u.downloadAndInstall(rawUrl)
}

func (u *Updater) downloadAndInstall(rawUrl string) error {
	url, err := url.Parse(rawUrl)
	if err != nil {
		return err
	}

	g := new(getter.HttpGetter)
	configDir := u.Config.GetUserConfigDir()
	u.Log.Info("Download directory is " + configDir)

	// Get it!
	if err := g.Get(configDir, url); err != nil {
		return err
	}

	// get the path of the current binary
	binaryPath, err := osext.Executable()
	if err != nil {
		return err
	}
	u.Log.Info("Binary path is " + binaryPath)

	binaryName := filepath.Base(binaryPath)
	u.Log.Info("Binary name is " + binaryName)

	// Verify the main file exists
	tempPath := filepath.Join(configDir, binaryName)
	u.Log.Info("Temp path to binary is " + tempPath)
	if _, err := os.Stat(tempPath); err != nil {
		return err
	}

	// swap out the old binary for the new one
Repository: jesseduffield/lazygit
File: pkg/gui/files_panel.go (Go)

Code before:
	}
	if err != nil {
		_ = gui.createErrorPanel(g, err.Error())
	}

	if err := gui.refreshFiles(); err != nil {
		return err
	}

	return gui.selectFile(false)
}

func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
	file, err := gui.getSelectedFile(gui.g)
	if err != nil {
		return gui.createErrorPanel(gui.g, err.Error())
	}

	if file.Tracked {
		return gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("IgnoreTracked"), gui.Tr.SLocalize("IgnoreTrackedPrompt"),
			// On confirmation
			func(_ *gocui.Gui, _ *gocui.View) error {
				if err := gui.GitCommand.Ignore(file.Name); err != nil {
					return err
				}
				if err := gui.GitCommand.OSCommand.RunCommand("git rm -r --cached %s", file.Name); err != nil {
					return err
				}
				return gui.refreshFiles()
			}, nil)
	}

	if err := gui.GitCommand.Ignore(file.Name); err != nil {
		return gui.createErrorPanel(gui.g, err.Error())
	}

	return gui.refreshFiles()
}

func (gui *Gui) handleWIPCommitPress(g *gocui.Gui, filesView *gocui.View) error {
	skipHookPreifx := gui.Config.GetUserConfig().GetString("git.skipHookPrefix")
	if skipHookPreifx == "" {
		return gui.createErrorPanel(gui.g, gui.Tr.SLocalize("SkipHookPrefixNotConfigured"))
	}

	if err := gui.renderString(g, "commitMessage", skipHookPreifx); err != nil {
		return err
	}
	if err := gui.getCommitMessageView().SetCursor(len(skipHookPreifx), 0); err != nil {
		return err
	}

Review comment (refactor):
could we move this into its own function in `git.go`? Just so that we're keeping all the git command-line stuff in the one place

Code after:
	}
	if err != nil {
		_ = gui.createErrorPanel(g, err.Error())
	}

	if err := gui.refreshFiles(); err != nil {
		return err
	}

	return gui.selectFile(false)
}

func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
	file, err := gui.getSelectedFile(gui.g)
	if err != nil {
		return gui.createErrorPanel(gui.g, err.Error())
	}

	if file.Tracked {
		return gui.createConfirmationPanel(gui.g, gui.g.CurrentView(), true, gui.Tr.SLocalize("IgnoreTracked"), gui.Tr.SLocalize("IgnoreTrackedPrompt"),
			// On confirmation
			func(_ *gocui.Gui, _ *gocui.View) error {
				if err := gui.GitCommand.Ignore(file.Name); err != nil {
					return err
				}
				if err := gui.GitCommand.RemoveTrackedFiles(file.Name); err != nil {
					return err
				}
				return gui.refreshFiles()
			}, nil)
	}

	if err := gui.GitCommand.Ignore(file.Name); err != nil {
		return gui.createErrorPanel(gui.g, err.Error())
	}

	return gui.refreshFiles()
}

func (gui *Gui) handleWIPCommitPress(g *gocui.Gui, filesView *gocui.View) error {
	skipHookPreifx := gui.Config.GetUserConfig().GetString("git.skipHookPrefix")
	if skipHookPreifx == "" {
		return gui.createErrorPanel(gui.g, gui.Tr.SLocalize("SkipHookPrefixNotConfigured"))
	}

	if err := gui.renderString(g, "commitMessage", skipHookPreifx); err != nil {
		return err
	}
	if err := gui.getCommitMessageView().SetCursor(len(skipHookPreifx), 0); err != nil {
		return err
	}
Repository: jesseduffield/lazygit
File: main.go (Go)

Code before:

	debuggingFlag := false
	flaggy.Bool(&debuggingFlag, "d", "debug", "Run in debug mode with logging")

	configFlag := false
	flaggy.Bool(&configFlag, "c", "config", "Print the current default config")

	flaggy.Parse()

	if versionFlag {
		fmt.Printf("commit=%s, build date=%s, build source=%s, version=%s, os=%s, arch=%s\n", commit, date, buildSource, version, runtime.GOOS, runtime.GOARCH)
		os.Exit(0)
	}

	if configFlag {
		fmt.Printf("%s\n", config.GetDefaultConfig())
		os.Exit(0)
	}

	if repoPath != "." {
		if err := os.Chdir(repoPath); err != nil {
			log.Fatal(err.Error())
		}
	}

	appConfig, err := config.NewAppConfig("lazygit", version, commit, date, buildSource, debuggingFlag, nil)
	if err != nil {
		log.Fatal(err.Error())
	}

	app, err := app.NewApp(appConfig)

	if err == nil {
		err = app.Run()
	}

	if err != nil {
		if errorMessage, known := app.KnownError(err); known {
			log.Fatal(errorMessage)
		}
		newErr := errors.Wrap(err, 0)
		stackTrace := newErr.ErrorStack()
		app.Log.Error(stackTrace)

		log.Fatal(fmt.Sprintf("%s\n\n%s", app.Tr.SLocalize("ErrorOccurred"), stackTrace))
	}
}


Review comment (suggestion):
I'm slightly confused here: we're allowing a services map to be passed in but I can't see anywhere that we are passing it in here. It seems to me that we don't need services mentioned in main.go and can leave it to app_config.go

Code after:
	debuggingFlag := false
	flaggy.Bool(&debuggingFlag, "d", "debug", "Run in debug mode with logging")

	configFlag := false
	flaggy.Bool(&configFlag, "c", "config", "Print the current default config")

	flaggy.Parse()

	if versionFlag {
		fmt.Printf("commit=%s, build date=%s, build source=%s, version=%s, os=%s, arch=%s\n", commit, date, buildSource, version, runtime.GOOS, runtime.GOARCH)
		os.Exit(0)
	}

	if configFlag {
		fmt.Printf("%s\n", config.GetDefaultConfig())
		os.Exit(0)
	}

	if repoPath != "." {
		if err := os.Chdir(repoPath); err != nil {
			log.Fatal(err.Error())
		}
	}

	appConfig, err := config.NewAppConfig("lazygit", version, commit, date, buildSource, debuggingFlag)
	if err != nil {
		log.Fatal(err.Error())
	}

	app, err := app.NewApp(appConfig)

	if err == nil {
		err = app.Run()
	}

	if err != nil {
		if errorMessage, known := app.KnownError(err); known {
			log.Fatal(errorMessage)
		}
		newErr := errors.Wrap(err, 0)
		stackTrace := newErr.ErrorStack()
		app.Log.Error(stackTrace)

		log.Fatal(fmt.Sprintf("%s\n\n%s", app.Tr.SLocalize("ErrorOccurred"), stackTrace))
	}
}
Repository: jesseduffield/lazygit
File: pkg/config/config_windows.go (Go)

Code before:
package config

// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() []byte {
	return []byte(
		`os:
  openCommand: 'cmd /c "start "" {{filename}}"'
  openLinkCommand: 'cmd /c "start "" {{link}}"'
  copyToClipboardCommand: 'cmd /c "echo -n {{str}} > /dev/clipboard"'`)
}


Review comment (suggestion):
```sh
echo -n {{str}} > /dev/clipboard
```
This wont work on windows :smile:  
I think you'll have to spawn powershell with this command: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-clipboard?view=powershell-7  
Or use the windows API via those dll files that would be the best solution here but i have never used that  

Oh one note, spawning powershell could result in lazygit getting labeled as a virus by some virus scanners. Had this issue myself with this tool https://github.com/dennis1248/OpenOEM it makes heavily use of spawning powershell prompts

Code after:
package config

// GetPlatformDefaultConfig gets the defaults for the platform
func GetPlatformDefaultConfig() []byte {
	return []byte(
		`os:
  openCommand: 'cmd /c "start "" {{filename}}"'
  openLinkCommand: 'cmd /c "start "" {{link}}"'`)
}