This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 245236
Collapse All | Expand All

(-)libs.git/apichanges.xml (+22 lines)
Lines 112-117 Link Here
112
        <change>
112
        <change>
113
            <api name="gitlibrary_api"/>
113
            <api name="gitlibrary_api"/>
114
            <summary>New method for updating a reference (branch) to a new commit id.</summary>
114
            <summary>New method for updating a reference (branch) to a new commit id.</summary>
115
            <version major="1" minor="26"/>
116
            <date day="25" month="6" year="2014"/>
117
            <author login="ovrabec"/>
118
            <compatibility addition="yes"/>
119
            <description>
120
                <ul>
121
                    <li>Git client accepts the parameter telling the merge command how
122
                    to proceed with regard to fast-forward commits. Users may require
123
                    either to enforce or to completely eliminate (and always create a merge commit)
124
                    fast-forward merges.</li>
125
                    <li>Git Repository instance allows users to query for the current default fast-forward
126
                    option via a new getter method.</li>
127
                </ul>
128
            </description>
129
            <class package="org.netbeans.libs.git" name="GitRepository"/>
130
            <class package="org.netbeans.libs.git" name="GitClient"/>
131
            <class package="org.netbeans.libs.git" name="GitMergeResult"/>
132
            <issue number="245236"/>
133
        </change>
134
        <change>
135
            <api name="gitlibrary_api"/>
136
            <summary>New method for updating a reference (branch) to a new commit id.</summary>
115
            <version major="1" minor="24"/>
137
            <version major="1" minor="24"/>
116
            <date day="23" month="6" year="2014"/>
138
            <date day="23" month="6" year="2014"/>
117
            <author login="ovrabec"/>
139
            <author login="ovrabec"/>
(-)libs.git/manifest.mf (-1 / +1 lines)
Lines 1-4 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.libs.git/1
2
OpenIDE-Module: org.netbeans.libs.git/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/libs/git/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/libs/git/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.25
4
OpenIDE-Module-Specification-Version: 1.26
(-)libs.git/src/org/netbeans/libs/git/GitClient.java (-2 / +20 lines)
Lines 53-58 Link Here
53
import org.eclipse.jgit.lib.PersonIdent;
53
import org.eclipse.jgit.lib.PersonIdent;
54
import org.eclipse.jgit.lib.Repository;
54
import org.eclipse.jgit.lib.Repository;
55
import org.eclipse.jgit.lib.RepositoryState;
55
import org.eclipse.jgit.lib.RepositoryState;
56
import org.netbeans.libs.git.GitRepository.FastForwardOption;
56
import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
57
import org.netbeans.libs.git.GitRevisionInfo.GitFileInfo;
57
import org.netbeans.libs.git.jgit.GitClassFactory;
58
import org.netbeans.libs.git.jgit.GitClassFactory;
58
import org.netbeans.libs.git.jgit.JGitCredentialsProvider;
59
import org.netbeans.libs.git.jgit.JGitCredentialsProvider;
Lines 867-873 Link Here
867
    }
868
    }
868
    
869
    
869
    /**
870
    /**
870
     * Merges a given revision with the current head
871
     * Merges a given revision with the current head.
872
     *
873
     * Fast-forward option will default to the one stated in .git/config.
874
     *
871
     * @param revision id of a revision to merge.
875
     * @param revision id of a revision to merge.
872
     * @param monitor progress monitor
876
     * @param monitor progress monitor
873
     * @return result of the merge
877
     * @return result of the merge
Lines 875-882 Link Here
875
     * @throws GitException an unexpected error occurs
879
     * @throws GitException an unexpected error occurs
876
     */
880
     */
877
    public GitMergeResult merge (String revision, ProgressMonitor monitor) throws GitException.CheckoutConflictException, GitException {
881
    public GitMergeResult merge (String revision, ProgressMonitor monitor) throws GitException.CheckoutConflictException, GitException {
882
        return merge(revision, null, monitor);
883
    }
884
    
885
    /**
886
     * Merges a given revision with the current head.
887
     * @param revision id of a revision to merge.
888
     * @param fastForward option telling merge to enforce or disable fast forward merges.
889
     * @param monitor progress monitor
890
     * @return result of the merge
891
     * @throws GitException.CheckoutConflictException there are local modifications in Working Tree, merge fails in such a case
892
     * @throws GitException an unexpected error occurs
893
     * @since 1.26
894
     */
895
    public GitMergeResult merge (String revision, FastForwardOption fastForward, ProgressMonitor monitor) throws GitException.CheckoutConflictException, GitException {
878
        Repository repository = gitRepository.getRepository();
896
        Repository repository = gitRepository.getRepository();
879
        MergeCommand cmd = new MergeCommand(repository, getClassFactory(), revision, monitor);
897
        MergeCommand cmd = new MergeCommand(repository, getClassFactory(), revision, fastForward, monitor);
880
        cmd.execute();
898
        cmd.execute();
881
        return cmd.getResult();
899
        return cmd.getResult();
882
    }
900
    }
(-)libs.git/src/org/netbeans/libs/git/GitMergeResult.java (-2 / +10 lines)
Lines 78-83 Link Here
78
                return "Fast-forward";
78
                return "Fast-forward";
79
            }
79
            }
80
        },
80
        },
81
        /**
82
         * Fast forward merge cannot be executed, a commit is needed.
83
         * @since 1.26
84
         */
85
        ABORTED {
86
            @Override
87
            public String toString() {
88
                return "Aborted";
89
            }
90
        },
81
        ALREADY_UP_TO_DATE {
91
        ALREADY_UP_TO_DATE {
82
            @Override
92
            @Override
83
            public String toString() {
93
            public String toString() {
Lines 178-185 Link Here
178
            mergeStatus = MergeResult.MergeStatus.MERGED;
188
            mergeStatus = MergeResult.MergeStatus.MERGED;
179
        } else if (mergeStatus == MergeResult.MergeStatus.MERGED_SQUASHED_NOT_COMMITTED) {
189
        } else if (mergeStatus == MergeResult.MergeStatus.MERGED_SQUASHED_NOT_COMMITTED) {
180
            mergeStatus = MergeResult.MergeStatus.MERGED;
190
            mergeStatus = MergeResult.MergeStatus.MERGED;
181
        } else if (mergeStatus == MergeResult.MergeStatus.ABORTED) {
182
            mergeStatus = MergeResult.MergeStatus.FAILED;
183
        } else if (mergeStatus == MergeResult.MergeStatus.CHECKOUT_CONFLICT) {
191
        } else if (mergeStatus == MergeResult.MergeStatus.CHECKOUT_CONFLICT) {
184
            mergeStatus = MergeResult.MergeStatus.CONFLICTING;
192
            mergeStatus = MergeResult.MergeStatus.CONFLICTING;
185
        }
193
        }
(-)libs.git/src/org/netbeans/libs/git/GitRepository.java (-1 / +84 lines)
Lines 45-50 Link Here
45
import java.io.File;
45
import java.io.File;
46
import java.util.Map;
46
import java.util.Map;
47
import java.util.WeakHashMap;
47
import java.util.WeakHashMap;
48
import org.eclipse.jgit.api.MergeCommand;
49
import org.eclipse.jgit.merge.MergeConfig;
48
import org.eclipse.jgit.transport.SshSessionFactory;
50
import org.eclipse.jgit.transport.SshSessionFactory;
49
import org.netbeans.libs.git.jgit.JGitRepository;
51
import org.netbeans.libs.git.jgit.JGitRepository;
50
import org.netbeans.libs.git.jgit.JGitSshSessionFactory;
52
import org.netbeans.libs.git.jgit.JGitSshSessionFactory;
Lines 77-83 Link Here
77
    private static final Map<File, GitRepository> repositoryPool = new WeakHashMap<File, GitRepository>(5);
79
    private static final Map<File, GitRepository> repositoryPool = new WeakHashMap<File, GitRepository>(5);
78
    private final File repositoryLocation;
80
    private final File repositoryLocation;
79
    private JGitRepository gitRepository;
81
    private JGitRepository gitRepository;
82
    
83
    /**
84
     * Option specifying how to deal with merges and merge commits. Required by
85
     * {@link GitClient#merge(java.lang.String, org.netbeans.libs.git.GitRepository.FastForwardOption, org.netbeans.libs.git.progress.ProgressMonitor)}.
86
     * To get the repository's default value, get it with {@link #getDefaultFastForwardOption()}.
87
     *
88
     * @since 1.26
89
     */
90
    public enum FastForwardOption {
80
91
92
        /**
93
         * Merge will not create a new commit if possible and only update the
94
         * branch reference to the merged commit. This will usually happen if
95
         * the merged commit is a descendant of the branch's head commit.
96
         */
97
        FAST_FORWARD {
98
99
            @Override
100
            public String toString () {
101
                return "--ff"; //NOI18N
102
            }
103
            
104
        },
105
        
106
        /**
107
         * Merge will fail if fast forward is impossible, no merge commit will
108
         * be created under any circumstances.
109
         */
110
        FAST_FORWARD_ONLY {
111
112
            @Override
113
            public String toString () {
114
                return "--ff-only"; //NOI18N
115
            }
116
            
117
        },
118
        
119
        /**
120
         * Will always create a merge commit even if fast forward were possible.
121
         */
122
        NO_FAST_FORWARD {
123
124
            @Override
125
            public String toString () {
126
                return "--no-ff"; //NOI18N
127
            }
128
            
129
        };
130
    }
131
81
    /**
132
    /**
82
     * Returns the instance of {@link GitRepository} representing an existing or not yet existing repository
133
     * Returns the instance of {@link GitRepository} representing an existing or not yet existing repository
83
     * specified by the given local folder.
134
     * specified by the given local folder.
Lines 109-119 Link Here
109
     * @throws GitException when an error occurs while loading repository data from disk.
160
     * @throws GitException when an error occurs while loading repository data from disk.
110
     */
161
     */
111
    public synchronized GitClient createClient () throws GitException {
162
    public synchronized GitClient createClient () throws GitException {
163
        getRepository();
164
        return createClient(gitRepository);
165
    }
166
    
167
    /**
168
     * Parses the repository configuration file and returns the default fast-forward merge
169
     * option set for the repository and its current branch.
170
     * 
171
     * @return the default fast-forward option for the current repository and the active branch.
172
     * @throws GitException an error occurs
173
     * @since 1.26
174
     */
175
    public FastForwardOption getDefaultFastForwardOption () throws GitException {
176
        JGitRepository repository = getRepository();
177
        repository.increaseClientUsage();
178
        try {
179
            MergeConfig cfg = MergeConfig.getConfigForCurrentBranch(repository.getRepository());
180
            MergeCommand.FastForwardMode mode = cfg.getFastForwardMode();
181
            switch (mode) {
182
                case FF_ONLY:
183
                    return FastForwardOption.FAST_FORWARD_ONLY;
184
                case NO_FF:
185
                    return FastForwardOption.NO_FAST_FORWARD;
186
                default:
187
                    return FastForwardOption.FAST_FORWARD;
188
            }
189
        } finally {
190
            repository.decreaseClientUsage();
191
        }
192
    }
193
194
    private synchronized JGitRepository getRepository () {
112
        if (gitRepository == null) {
195
        if (gitRepository == null) {
113
            gitRepository = new JGitRepository(repositoryLocation);
196
            gitRepository = new JGitRepository(repositoryLocation);
114
            SshSessionFactory.setInstance(JGitSshSessionFactory.getDefault());
197
            SshSessionFactory.setInstance(JGitSshSessionFactory.getDefault());
115
        }
198
        }
116
        return createClient(gitRepository);
199
        return gitRepository;
117
    }
200
    }
118
201
119
    /**
202
    /**
(-)libs.git/src/org/netbeans/libs/git/jgit/commands/MergeCommand.java (-2 / +29 lines)
Lines 52-57 Link Here
52
import org.eclipse.jgit.lib.Repository;
52
import org.eclipse.jgit.lib.Repository;
53
import org.netbeans.libs.git.GitException;
53
import org.netbeans.libs.git.GitException;
54
import org.netbeans.libs.git.GitMergeResult;
54
import org.netbeans.libs.git.GitMergeResult;
55
import org.netbeans.libs.git.GitRepository.FastForwardOption;
55
import org.netbeans.libs.git.jgit.GitClassFactory;
56
import org.netbeans.libs.git.jgit.GitClassFactory;
56
import org.netbeans.libs.git.jgit.Utils;
57
import org.netbeans.libs.git.jgit.Utils;
57
import org.netbeans.libs.git.progress.ProgressMonitor;
58
import org.netbeans.libs.git.progress.ProgressMonitor;
Lines 64-72 Link Here
64
    private final String revision;
65
    private final String revision;
65
    private GitMergeResult result;
66
    private GitMergeResult result;
66
    private String commitMessage;
67
    private String commitMessage;
68
    private final FastForwardOption ffOption;
67
69
68
    public MergeCommand (Repository repository, GitClassFactory gitFactory, String revision, ProgressMonitor monitor) {
70
    public MergeCommand (Repository repository, GitClassFactory gitFactory, String revision,
71
            FastForwardOption ffOption, ProgressMonitor monitor) {
69
        super(repository, gitFactory, monitor);
72
        super(repository, gitFactory, monitor);
73
        this.ffOption = ffOption;
70
        this.revision = revision;
74
        this.revision = revision;
71
    }
75
    }
72
76
Lines 74-79 Link Here
74
    protected void run () throws GitException {
78
    protected void run () throws GitException {
75
        Repository repository = getRepository();
79
        Repository repository = getRepository();
76
        org.eclipse.jgit.api.MergeCommand command = new Git(repository).merge();
80
        org.eclipse.jgit.api.MergeCommand command = new Git(repository).merge();
81
        setFastForward(command);
77
        Ref ref = null;
82
        Ref ref = null;
78
        try {
83
        try {
79
            ref = repository.getRef(revision);
84
            ref = repository.getRef(revision);
Lines 106-112 Link Here
106
111
107
    @Override
112
    @Override
108
    protected String getCommandDescription () {
113
    protected String getCommandDescription () {
109
        return new StringBuilder("git merge ").append(revision).toString(); //NOI18N
114
        StringBuilder sb = new StringBuilder("git merge "); //NOI18N
115
        if (ffOption != null) {
116
            sb.append(ffOption).append(" "); //NOI18N
117
        }
118
        return sb.append(revision).toString();
110
    }
119
    }
111
120
112
    public GitMergeResult getResult () {
121
    public GitMergeResult getResult () {
Lines 127-130 Link Here
127
        }
136
        }
128
        throw new GitException(original);
137
        throw new GitException(original);
129
    }
138
    }
139
140
    private void setFastForward (org.eclipse.jgit.api.MergeCommand cmd) {
141
        if (ffOption == null) {
142
            // will fall back on the config default
143
            return;
144
        }
145
        switch (ffOption) {
146
            case FAST_FORWARD:
147
                cmd.setFastForward(org.eclipse.jgit.api.MergeCommand.FastForwardMode.FF);
148
                break;
149
            case FAST_FORWARD_ONLY:
150
                cmd.setFastForward(org.eclipse.jgit.api.MergeCommand.FastForwardMode.FF_ONLY);
151
                break;
152
            case NO_FAST_FORWARD:
153
                cmd.setFastForward(org.eclipse.jgit.api.MergeCommand.FastForwardMode.NO_FF);
154
                break;
155
        }
156
    }
130
}
157
}
(-)libs.git/src/org/netbeans/libs/git/jgit/commands/PullCommand.java (-1 / +1 lines)
Lines 85-91 Link Here
85
        fetch.setCredentialsProvider(getCredentialsProvider());
85
        fetch.setCredentialsProvider(getCredentialsProvider());
86
        fetch.run();
86
        fetch.run();
87
        this.updates = fetch.getUpdates();
87
        this.updates = fetch.getUpdates();
88
        MergeCommand merge = new MergeCommand(getRepository(), getClassFactory(), branchToMerge, monitor);
88
        MergeCommand merge = new MergeCommand(getRepository(), getClassFactory(), branchToMerge, null, monitor);
89
        merge.setCommitMessage("branch \'" + findRemoteBranchName() + "\' of " + fetch.getResult().getURI().setUser(null).setPass(null).toString());
89
        merge.setCommitMessage("branch \'" + findRemoteBranchName() + "\' of " + fetch.getResult().getURI().setUser(null).setPass(null).toString());
90
        merge.run();
90
        merge.run();
91
        this.mergeResult = merge.getResult();
91
        this.mergeResult = merge.getResult();
(-)libs.git/test/unit/src/org/netbeans/libs/git/jgit/commands/MergeTest.java (+86 lines)
Lines 56-61 Link Here
56
import org.netbeans.libs.git.GitException;
56
import org.netbeans.libs.git.GitException;
57
import org.netbeans.libs.git.GitMergeResult;
57
import org.netbeans.libs.git.GitMergeResult;
58
import org.netbeans.libs.git.GitMergeResult.MergeStatus;
58
import org.netbeans.libs.git.GitMergeResult.MergeStatus;
59
import org.netbeans.libs.git.GitRepository;
59
import org.netbeans.libs.git.GitRevisionInfo;
60
import org.netbeans.libs.git.GitRevisionInfo;
60
import org.netbeans.libs.git.GitTransportUpdate;
61
import org.netbeans.libs.git.GitTransportUpdate;
61
import org.netbeans.libs.git.SearchCriteria;
62
import org.netbeans.libs.git.SearchCriteria;
Lines 381-384 Link Here
381
        client.checkoutRevision(Constants.MASTER, true, NULL_PROGRESS_MONITOR);
382
        client.checkoutRevision(Constants.MASTER, true, NULL_PROGRESS_MONITOR);
382
        client.merge(BRANCH_NAME, NULL_PROGRESS_MONITOR);
383
        client.merge(BRANCH_NAME, NULL_PROGRESS_MONITOR);
383
    }
384
    }
385
    
386
    public void testMergeNoFastForward () throws Exception {
387
        File f = new File(workDir, "file");
388
        write(f, "init");
389
        add(f);
390
        commit(f);
391
        
392
        GitClient client = getClient(workDir);
393
        client.createBranch(BRANCH_NAME, Constants.MASTER, NULL_PROGRESS_MONITOR);
394
        client.checkoutRevision(BRANCH_NAME, true, NULL_PROGRESS_MONITOR);
395
        write(f, BRANCH_NAME);
396
        add(f);
397
        GitRevisionInfo info = client.commit(new File[] { f }, "change on branch", null, null, NULL_PROGRESS_MONITOR);
398
        client.checkoutRevision(Constants.MASTER, true, NULL_PROGRESS_MONITOR);
399
        
400
        assertEquals("init", read(f));
401
        
402
        GitMergeResult result = client.merge(BRANCH_NAME, NULL_PROGRESS_MONITOR);
403
        assertEquals(MergeStatus.FAST_FORWARD, result.getMergeStatus());
404
        assertEquals(BRANCH_NAME, read(f));
405
        
406
        SearchCriteria crit = new SearchCriteria();
407
        crit.setRevisionTo(Constants.MASTER);
408
        GitRevisionInfo[] logs = client.log(crit, NULL_PROGRESS_MONITOR);
409
        assertEquals(2, logs.length);
410
        assertEquals(logs[0].getRevision(), info.getRevision());
411
        
412
        // continue working on branch
413
        client.checkoutRevision(BRANCH_NAME, true, NULL_PROGRESS_MONITOR);
414
        remove(false, f);
415
        client.commit(new File[] { f }, "delete on branch", null, null, NULL_PROGRESS_MONITOR);
416
        client.checkoutRevision(Constants.MASTER, true, NULL_PROGRESS_MONITOR);
417
        
418
        assertEquals(BRANCH_NAME, read(f));
419
        
420
        result = client.merge(BRANCH_NAME, GitRepository.FastForwardOption.NO_FAST_FORWARD, NULL_PROGRESS_MONITOR);
421
        assertEquals(MergeStatus.MERGED, result.getMergeStatus());
422
        assertFalse(f.exists());
423
        
424
        crit = new SearchCriteria();
425
        crit.setRevisionTo(Constants.MASTER);
426
        logs = client.log(crit, NULL_PROGRESS_MONITOR);
427
        assertEquals(4, logs.length);
428
        assertEquals(2, logs[0].getParents().length);
429
    }
430
    
431
    public void testMergeFFOnly () throws Exception {
432
        File f1 = new File(workDir, "file1");
433
        File f2 = new File(workDir, "file2");
434
        write(f1, "init");
435
        write(f2, "init");
436
        add(f1, f2);
437
        commit(f1, f2);
438
        
439
        GitClient client = getClient(workDir);
440
        client.createBranch(BRANCH_NAME, Constants.MASTER, NULL_PROGRESS_MONITOR);
441
        client.checkoutRevision(BRANCH_NAME, true, NULL_PROGRESS_MONITOR);
442
        write(f1, BRANCH_NAME);
443
        add(f1);
444
        client.commit(new File[] { f1 }, "change on branch", null, null, NULL_PROGRESS_MONITOR);
445
        client.checkoutRevision(Constants.MASTER, true, NULL_PROGRESS_MONITOR);
446
        write(f2, "another change");
447
        add(f2);
448
        client.commit(new File[] { f2 }, "change on master", null, null, NULL_PROGRESS_MONITOR);
449
        
450
        GitMergeResult result = client.merge(BRANCH_NAME, GitRepository.FastForwardOption.FAST_FORWARD_ONLY, NULL_PROGRESS_MONITOR);
451
        // no merge commits allowed => FAIL
452
        assertEquals(MergeStatus.ABORTED, result.getMergeStatus());
453
        
454
        // test also config files
455
        assertEquals(GitRepository.FastForwardOption.FAST_FORWARD, GitRepository.getInstance(workDir).getDefaultFastForwardOption());
456
        
457
        StoredConfig cfg = repo.getConfig();
458
        cfg.setEnum(ConfigConstants.CONFIG_KEY_MERGE, null,
459
                    ConfigConstants.CONFIG_KEY_FF, org.eclipse.jgit.api.MergeCommand.FastForwardMode.Merge.ONLY);
460
        cfg.save();
461
        assertEquals(GitRepository.FastForwardOption.FAST_FORWARD_ONLY, GitRepository.getInstance(workDir).getDefaultFastForwardOption());
462
        result = client.merge(BRANCH_NAME, NULL_PROGRESS_MONITOR);
463
        // no merge commits allowed => FAIL
464
        assertEquals(MergeStatus.ABORTED, result.getMergeStatus());
465
        
466
        result = client.merge(BRANCH_NAME, GitRepository.FastForwardOption.FAST_FORWARD, NULL_PROGRESS_MONITOR);
467
        // merge commits allowed => OK
468
        assertEquals(MergeStatus.MERGED, result.getMergeStatus());
469
    }
384
}
470
}

Return to bug 245236