Author Topic: "Could not open Perforce SCM project Perforce Project" error with SlickEdit v25  (Read 2064 times)

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
After upgrading to SlickEdit v25.0.0.8 32-bit, trying to check out a file from Perforce gives me this message:
Quote
---------------------------
SlickEdit Pro
---------------------------
You must first open a project(Tools...Version Control...Setup)
---------------------------
OK   
---------------------------

After selecting "Tools -> Version Control (Perforce SCM(SCC)) -> Setup -> Open Project" and completing the "Open Connection" dialog (Version P4SCC/NTX86/2010.1/271261), then everything works as expected.  However, after closing SlickEdit and opening it again I get the error:
Quote
---------------------------
SlickEdit Pro
---------------------------
Could not open Perforce SCM project Perforce Project
---------------------------
OK   
---------------------------

and then I need to go through the steps of opening the version control project again.  This did not happen in SlickEdit v24.

My "Help -> About SlickEdit" output:
Quote
SlickEdit Pro 2020 (v25.0.0.8 32-bit)

Serial number: WB943076
Licensed number of users: Single user
License file: C:\ProgramData\slickedit\25\slickedit.lic

Build Date: October 2, 2020
Emulation: CUA

OS: Windows 10 x64
OS Version: 10.00.0 
Memory: 49% Load, 8093MB/16292MB Physical, 14948MB/29604MB Page File, 919MB/4095MB Virtual
Shell Information: C:\tools\JPSoft\TCMD25\tcc.exe /LD /LH
Screen Size: 2560 x 1440

Project Type: Other
Language: .h (C/C++)
Encoding: ACP (1252)

Installation Directory: C:\Program Files (x86)\SlickEdit Pro 25.0.0\ (non-removable drive,NTFS,115486MB free)
Configuration Directory: C:\Users\sigmund\Documents\My SlickEdit Config\25.0.0\ (non-removable drive,NTFS,115486MB free)
Migrated from: C:\Users\sigmund\Documents\My SlickEdit Config\24.0.1\

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
After generating a SlickEdit project file (through our python SlickEdit project generator) it starts with this:
Code: [Select]
<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
<Project
        Version="10.0"
        VendorName="SlickEdit"
        WorkingDir="D:\clean\tools\vx"
        VCSAuxPath="0"
        VCSProject="SCC:Perforce SCM:Perforce Project">
        <Config
...

But after opening a workspace that uses this project in SlickEdit v25 and closing it again it looks like this:
Code: [Select]
<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
<Project
    Version="10.0"
    VendorName="SlickEdit"
    WorkingDir="D:\clean\tools\vx"
    VCSAuxPath="0">
    <Config
...

(Edit: The project file actually gets modified when opening the workspace, right after hitting the "Could not open Perforce SCM project Perforce Project" dialog's OK button.)
« Last Edit: October 15, 2020, 09:28:23 AM by sigmund »

Dan

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 2903
  • Hero Points: 153
I will take a look at this.

Have you tried our newer support for Perforce?  To try it, pick the command line version support.  It does more than the SCC support, and it would allow you to run the 64-bit SlickEdit.

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
Thank you very much for the tip, I have switch to the command line version now (and 64-bit SlickEdit, yay!).

The only thing I am not very happy about is the order of the old/new (original/modified) files when diffing as I explain here:
https://community.slickedit.com/index.php/topic,15257.msg70337.html#msg70337

Dan

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 2903
  • Hero Points: 153
This should be addressed in 26.0.

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
Just as I was starting to think that 2020 finally is starting to look better ;)

I guess I will try to figure out some kind of hack until then.

Dan

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 2903
  • Hero Points: 153
Actually the plan is to change the Compare workspace/project/directory with Perforce to use a different dialog, and that dialog has a switch for left/right.  Doing it in the normal diff dialog might be more difficult.

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
I do not understand why a --reverse-order switch or something is very difficult.

I will probably revert back to what I have used before:
Code: [Select]
// Diffs open workspace file against its have-revision.
// Suggested key binding: Ctrl+D
_command
vusrmacs_vcdiff() name_info(','VSARG2_EDITORCTL)
{
    _macro('R',1);

    if (!p_HasBuffer || (p_buf_flags & VSBUFFLAG_HIDDEN))
    {
        message('vusrmacs_vcdiff: A regular buffer is required.');
        return -1;
    }

    // vcdiff() crashes when using Perforce if the file is not under
    // version control or it is opened for add.
    if (def_vc_system == 'SCC:Perforce SCM')   // <-- this needs to change after switching to the p4 command line version
        _PerforceDiff();
    else
        execute('vcdiff');  // <-- execute('vcdiff --reverse-order'); ?
}

// Runs a diff between the have-revision of the current file and the
// current file itself.
static void
_PerforceDiff()
{
    _str diffToolPath = _GetDiffToolPath();
    if (diffToolPath == null)
    {
        message('vusrmacs_vcdiff: No diff tool found.');
        return;
    }

    _str filename = p_buf_name;

    _str tempDir = get_env('TEMP') :+ '\vcdiff\' :+
        stranslate(strip_filename(filename, 'N'), '', ':');
    make_path(tempDir);

    _str tempName = tempDir :+ strip_filename(filename, 'P');

    _str newDirectory = get_env('TREE_ROOT');
    if (newDirectory == '')
        newDirectory = strip_filename(filename, 'N');

    _str oldDirectory = getcwd();
    chdir(newDirectory, /* changeDrive */ 1);

    int shellReturnCode = shell(
        'p4.exe print "' :+ filename :+
        '"#have > "' :+ tempName :+ '" 2>&1', 'PQ');

    chdir(oldDirectory, /* changeDrive */ 1);

    int temp_view_id=0;
    int orig_view_id=0;
    int status = _open_temp_view(tempName, temp_view_id, orig_view_id);
    if (status != 0)
    {
        message('vusrmacs_vcdiff: Could not open "' :+ tempName :+ '".');
        return;
    }

    top();
    _str output;
    get_line(output);

    if (_CheckPerforceOutput(output, shellReturnCode))
    {
        _delete_line();

        _str revision = stranslate(output, '\1', '.*#([0-9]+) - .*', 'u');

        tempName = strip_filename(tempName, 'E') :+ '#' :+ revision :+
            _get_extension(tempName, /* returnDot */ true);

        save('+o 'tempName, SV_OVERWRITE|SV_NOADDFILEHIST);

        _str diffToolFlags = '';
        if (strip_filename(diffToolPath, 'P') == 'vsdiff.exe')
            diffToolFlags = ' -r1';

        // We run the diff asynchronously so that we can continue using
        // SlickEdit while the diff is in progress.
        shell('"' :+ diffToolPath :+ '"' :+ diffToolFlags :+ ' "' :+
            tempName :+ '" "' :+ filename :+ '"', 'APQ');
    }

    _delete_temp_view(temp_view_id);
    p_window_id = orig_view_id;
}

// Returns the path of the diff tool to use.
static _str
_GetDiffToolPath()
{
    _str path = null;

    // We could look for the diff tool in config files for different version
    // control systems, but for now we only check the P4V config file.

    if (true /* def_vc_system == 'SCC:Perforce SCM' */)
    {
        _str appsettingsFilename = get_env('USERPROFILE') :+
            '\.p4scc\appsettings.xml';

        int status = -1;
        int handle = _xmlcfg_open(
            appsettingsFilename, status, VSXMLCFG_OPEN_ADD_PCDATA);

        if (status != 0)
        {
            _str query = '//PropertyList/Associations[' \
                '@varName="Diff Associations"]/Association[' \
                '@varName="Default Association"]/Application/text()';

            int index = _xmlcfg_find_simple(handle, query);
            if (index >= 0)
                path = _xmlcfg_get_value_unindent(handle, index);

            _xmlcfg_close(handle);
        }
    }

    // Use vsdiff if no other diff tool was found.
    if (path == null)
        path = path_search('vsdiff.exe');

    if (path == '')
        path = null;

    return path;
}

// Returns true if the output of "p4 print" indicates no errors.
// Reports an error and returns false otherwise.
static boolean
_CheckPerforceOutput(
    _str output,
    int shellReturnCode)
{
    if (output == 'Perforce client error:')
    {
        while (down() == 0)
        {
            _str line;
            get_line(line);
            output = output :+ "\n" :+ line;
        }

        _message_box(output);

        return false;
    }

    if (shellReturnCode != 0)
    {
        message('vusrmacs_vcdiff: ' :+ output);

        return false;
    }

    if (pos(' - no such file\(s\)\.$', output, 1, 'u') > 0)
    {
        message('vusrmacs_vcdiff: "' :+ p_buf_name :+ '" is not ' \
            'under source control.');

        return false;
    }

    return true;
}

I do not like it, but it (kind of) works..

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
Another note: In my experience, even though "Tools -> Version Control (Perforce) -> Diff <file> with most up to date version" sometimes is useful, the more common thing to want is "Diff <file> with unmodified version" (the "have revision" in Perforce terminology, see the "#have" in the code above).

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
Another thing that it would be nice to get SlickEdit support for is version control "blame".  Here is some of the code I have been using for this:
Code: [Select]
// Creates a temporary file with version control annotations from the file open
// in the current buffer.
// Suggested key binding: Alt+B
_command
vusrmacs_vcblame() name_info(','VSARG2_MARK|VSARG2_REQUIRES_MDI_EDITORCTL|VSARG2_READ_ONLY)
{
    _macro('R',1);

    _str prevFilename = p_buf_name;
    _str filename = p_buf_name;

    _str tempDir = get_env('TEMP') :+ '\vcblame\' :+
        stranslate(strip_filename(p_buf_name, 'N'), '', ':');
    make_path(tempDir);

    _str tempName = tempDir :+ strip_filename(p_buf_name, 'P');

    _str treeRoot = get_env('TREE_ROOT');
    if (treeRoot == '')
        treeRoot = get_env('DEFAULT_TREE_ROOT');

    if (treeRoot == '')
    {
        message('vusrmacs_vcblame: The TREE_ROOT or DEFAULT_TREE_ROOT ' \
            'environment variable must be set in order to find scripts.');

        return -1;
    }

    // Changing the drive from within the shell command ("d: & cd d:\dev &...")
    // does not seem to work, so we use chdir() instead.
    _str oldDirectory = getcwd();
    chdir(strip_filename(filename, 'N'), /* changeDrive */ 1);

    int shellReturnCode = 0;
    boolean unknownVersionControl = false;

    if (def_vc_system == 'Git' ||
        svc_get_vc_system() == 'Git' ||
        pos(treeRoot, filename) != 1) // In this case we should search up the directory structure for a .git folder
    {
        // We do not really want to pass the -w flag:
        // http://stackoverflow.com/questions/4638500/git-blame-showing-no-history
        shellReturnCode = shell(
            '"C:\tools\Git\cmd\git.exe" blame -w ' :+
            maybe_quote_filename(filename) :+ ' > ' :+
            maybe_quote_filename(tempName) :+ ' 2>&1', 'PQ');
    }
    else if (def_vc_system == 'SCC:Perforce SCM')  // <-- this needs to change after switching to the p4 command line version
    {
        shellReturnCode = shell(
            'python.exe ' :+ treeRoot :+
            '\tools\infrastructure\p4blame\p4blame.py --no-line-numbers ' :+
            maybe_quote_filename(filename) :+ ' > ' :+
            maybe_quote_filename(tempName) :+ ' 2>&1', 'PQ');
    }
    else if (def_vc_system == 'SCC:Microsoft Team Foundation Server MSSCCI Provider')
    {
        // XXX:oops  We forgot to copy tfblame.py from NOV!
        shellReturnCode = shell(
            'python.exe c:\tools\infrastructure\tfblame.py' \
            ' --no-line-numbers --ignore-tf-errors ' :+
            maybe_quote_filename(filename) :+ ' > ' :+
            maybe_quote_filename(tempName) :+ ' 2>&1', 'PQ');
    }
    else
    {
        unknownVersionControl = true;
    }

    chdir(oldDirectory, /* changeDrive */ 1);

    if (unknownVersionControl)
    {
        message('vusrmacs_vcblame: Unknown version control system "' :+
            def_vc_system :+ '".');

        return -1;
    }
    else if (shellReturnCode != 0)
    {
        message('vusrmacs_vcblame: shell() failed with return code ' :+
            shellReturnCode :+ '.');

        return -1;
    }

    int line = p_line;
    int y0 = p_rel_line;

    edit(maybe_quote_filename(tempName), EDIT_NOADDHIST);
    goto_line(line);

    int y1 = p_rel_line;

    int i;
    for (i=0; i<y1-y0; i++)
        scroll_down();
    for (i=0; i<y0-y1; i++)
        scroll_up();
}

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
After switching from the SCC to the command line Perforce version, I needed to change the checks in the code above from:
Code: [Select]
    def_vc_system == 'SCC:Perforce SCM'
to
Code: [Select]
    svc_get_vc_system() == 'Perforce'

I see that svc_get_vc_system() takes a file path.  Is it possible to use multiple version control systems at the same time?  That would be very useful because I often temporarily open files from a Git repo in a Perforce workspace.  It would be nice to be able to switch to Git for files like this for version control command (kind of like what vusrmacs_vcblame() does above based on the file path).

Dan

  • SlickEdit Team Member
  • Senior Community Member
  • *
  • Posts: 2903
  • Hero Points: 153
If you go to Tools>Options>Tools>Version Control>Setup, you can set the version control system for a scope.  So you can set it to a different system for a different project or workspaces.

sigmund

  • Community Member
  • Posts: 97
  • Hero Points: 9
Nice!  Using _ProjectSet_VCSProject() I am able to achieve what I want.  This obviously needs some generalization and refactoring, but I can now use Perforce and Git at the same time:
Code: [Select]
// Diffs open workspace file against its have-revision.
// Suggested key binding: Ctrl+D
_command
vusrmacs_vcdiff() name_info(','VSARG2_EDITORCTL)
{
    _macro('R',1);

    if (!p_HasBuffer || (p_buf_flags & VSBUFFLAG_HIDDEN))
    {
        message('vusrmacs_vcdiff: A regular buffer is required.');
        return -1;
    }

    bool usePerforceDiff = false;
    _str vcs = svc_get_vc_system();
    _str guestVcs = '';

    if (vcs == 'Perforce')
    {
        if (pos(_perforce_info.clientRoot, p_buf_name, 1, 'I') == 1)
            usePerforceDiff = true;
        else
            guestVcs = 'Git';
    }

    if (usePerforceDiff)
    {
        _PerforceDiff();
    }
    else
    {
        if (guestVcs != '')
            _ProjectSet_VCSProject(_ProjectHandle(), guestVcs);

        execute('vcdiff');

        if (guestVcs != 0)
            _ProjectSet_VCSProject(_ProjectHandle(), vcs);
    }
}

// Shows the history for the file open in the current buffer.
// Suggested key binding: Alt+H
_command
vusrmacs_vchistory() name_info(','VSARG2_EDITORCTL)
{
    _macro('R',1);

    _str vcs = svc_get_vc_system();
    _str guestVcs = '';

    if (vcs == 'Perforce')
    {
        if (pos(_perforce_info.clientRoot, p_buf_name, 1, 'I') != 1)
            guestVcs = 'Git';
    }

    if (guestVcs != '')
        _ProjectSet_VCSProject(_ProjectHandle(), guestVcs);

    execute('vchistory');

    if (guestVcs != 0)
        _ProjectSet_VCSProject(_ProjectHandle(), vcs);
}