1 /*
2 * Copyright (C) 2011, Chris Aniszczyk <caniszczyk@gmail.com>
3 * and other copyright owners as documented in the project's IP log.
4 *
5 * This program and the accompanying materials are made available
6 * under the terms of the Eclipse Distribution License v1.0 which
7 * accompanies this distribution, is reproduced below, and is
8 * available at http://www.eclipse.org/org/documents/edl-v10.php
9 *
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
23 *
24 * - Neither the name of the Eclipse Foundation, Inc. nor the
25 * names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior
27 * written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43 package org.eclipse.jgit.api;
44
45 import java.io.IOException;
46
47 import org.eclipse.jgit.api.errors.GitAPIException;
48 import org.eclipse.jgit.api.errors.JGitInternalException;
49 import org.eclipse.jgit.lib.CommitBuilder;
50 import org.eclipse.jgit.lib.Constants;
51 import org.eclipse.jgit.lib.ObjectId;
52 import org.eclipse.jgit.lib.ObjectInserter;
53 import org.eclipse.jgit.lib.PersonIdent;
54 import org.eclipse.jgit.lib.Ref;
55 import org.eclipse.jgit.lib.RefUpdate;
56 import org.eclipse.jgit.lib.Repository;
57 import org.eclipse.jgit.notes.Note;
58 import org.eclipse.jgit.notes.NoteMap;
59 import org.eclipse.jgit.revwalk.RevCommit;
60 import org.eclipse.jgit.revwalk.RevObject;
61 import org.eclipse.jgit.revwalk.RevWalk;
62
63 /**
64 * Add object notes.
65 *
66 * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-notes.html"
67 * >Git documentation about Notes</a>
68 */
69 public class AddNoteCommand extends GitCommand<Note> {
70
71 private RevObject id;
72
73 private String message;
74
75 private String notesRef = Constants.R_NOTES_COMMITS;
76
77 /**
78 * Constructor for AddNoteCommand
79 *
80 * @param repo
81 * the {@link org.eclipse.jgit.lib.Repository}
82 */
83 protected AddNoteCommand(Repository repo) {
84 super(repo);
85 }
86
87 /** {@inheritDoc} */
88 @Override
89 public Note call() throws GitAPIException {
90 checkCallable();
91 NoteMap map = NoteMap.newEmptyMap();
92 RevCommit notesCommit = null;
93 try (RevWalk walk = new RevWalk(repo);
94 ObjectInserter inserter = repo.newObjectInserter()) {
95 Ref ref = repo.findRef(notesRef);
96 // if we have a notes ref, use it
97 if (ref != null) {
98 notesCommit = walk.parseCommit(ref.getObjectId());
99 map = NoteMap.read(walk.getObjectReader(), notesCommit);
100 }
101 map.set(id, message, inserter);
102 commitNoteMap(repo, notesRef, walk, map, notesCommit, inserter,
103 "Notes added by 'git notes add'"); //$NON-NLS-1$
104 return map.getNote(id);
105 } catch (IOException e) {
106 throw new JGitInternalException(e.getMessage(), e);
107 }
108 }
109
110 /**
111 * Sets the object id of object you want a note on. If the object already
112 * has a note, the existing note will be replaced.
113 *
114 * @param id
115 * a {@link org.eclipse.jgit.revwalk.RevObject}
116 * @return {@code this}
117 */
118 public AddNoteCommand setObjectId(RevObject id) {
119 checkCallable();
120 this.id = id;
121 return this;
122 }
123
124 /**
125 * Set the notes message
126 *
127 * @param message
128 * the notes message used when adding a note
129 * @return {@code this}
130 */
131 public AddNoteCommand setMessage(String message) {
132 checkCallable();
133 this.message = message;
134 return this;
135 }
136
137 static void commitNoteMap(Repository r, String ref, RevWalk walk,
138 NoteMap map,
139 RevCommit notesCommit,
140 ObjectInserter inserter,
141 String msg)
142 throws IOException {
143 // commit the note
144 CommitBuilder builder = new CommitBuilder();
145 builder.setTreeId(map.writeTree(inserter));
146 builder.setAuthor(new PersonIdent(r));
147 builder.setCommitter(builder.getAuthor());
148 builder.setMessage(msg);
149 if (notesCommit != null)
150 builder.setParentIds(notesCommit);
151 ObjectId commit = inserter.insert(builder);
152 inserter.flush();
153 RefUpdate refUpdate = r.updateRef(ref);
154 if (notesCommit != null)
155 refUpdate.setExpectedOldObjectId(notesCommit);
156 else
157 refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
158 refUpdate.setNewObjectId(commit);
159 refUpdate.update(walk);
160 }
161
162 /**
163 * Set name of a {@code Ref} to read notes from
164 *
165 * @param notesRef
166 * the ref to read notes from. Note, the default value of
167 * {@link org.eclipse.jgit.lib.Constants#R_NOTES_COMMITS} will be
168 * used if nothing is set
169 * @return {@code this}
170 * @see Constants#R_NOTES_COMMITS
171 */
172 public AddNoteCommand setNotesRef(String notesRef) {
173 checkCallable();
174 this.notesRef = notesRef;
175 return this;
176 }
177
178 }